在 Android 上启用 Fabric

Posted 小陈乱敲代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在 Android 上启用 Fabric相关的知识,希望对你有一定的参考价值。

1. 提供JSIModulePackage的内部ReactNativeHost

为了在您的应用程序中启用 Fabric,您需要JSIModulePackage在ReactNativeHost. 如果您遵循本指南的 TurboModule 部分,您可能已经知道在哪里可以找到您的ReactNativeHost. 如果没有,您可以ReactNativeHost通过搜索找到您的getReactNativeHost(). ReactNativeHost通常位于您的班级Application内。

找到它后,您需要添加getJSIModulePackage以下代码段中的方法:

MyApplication.java
public class MyApplication extends Application implements ReactApplication 

  private final ReactNativeHost mReactNativeHost =
    new ReactNativeHost(this) 

      // Add those lines:
      @Nullable
      @Override
      protected JSIModulePackage getJSIModulePackage() 
        return new JSIModulePackage() 
          @Override
          public List<JSIModuleSpec> getJSIModules(
              final ReactApplicationContext reactApplicationContext,
              final javascriptContextHolder jsContext) 
            final List<JSIModuleSpec> specs = new ArrayList<>();
            specs.add(new JSIModuleSpec() 
              @Override
              public JSIModuleType getJSIModuleType() 
                return JSIModuleType.UIManager;
              

              @Override
              public JSIModuleProvider<UIManager> getJSIModuleProvider() 
                final ComponentFactory componentFactory = new ComponentFactory();
                CoreComponentsRegistry.register(componentFactory);
                final ReactInstanceManager reactInstanceManager = getReactInstanceManager();

                ViewManagerRegistry viewManagerRegistry =
                    new ViewManagerRegistry(
                        reactInstanceManager.getOrCreateViewManagers(
                            reactApplicationContext));

                return new FabricJSIModuleProvider(
                    reactApplicationContext,
                    componentFactory,
                    new EmptyReactNativeConfig(),
                    viewManagerRegistry);
              
            );
            return specs;
          
        ;
      
    ;

2. 确保setIsFabric对 ActivityReactRootView

在你的课堂上,Activity你需要确保你正在调用setIsFabric.ReactRootView如果您没有,ReactActivityDelegate您可能需要创建一个。

public class MainActivity extends ReactActivity 

  // Add the Activity Delegate, if you don't have one already.
  public static class MainActivityDelegate extends ReactActivityDelegate 

    public MainActivityDelegate(ReactActivity activity, String mainComponentName) 
      super(activity, mainComponentName);
    

    @Override
    protected ReactRootView createRootView() 
      ReactRootView reactRootView = new ReactRootView(getContext());

      // Make sure to call setIsFabric(true) on your ReactRootView
      reactRootView.setIsFabric(true);
      return reactRootView;
    
  

  // Make sure to override the `createReactActivityDelegate()` method.
  @Override
  protected ReactActivityDelegate createReactActivityDelegate() 
    return new MainActivityDelegate(this, getMainComponentName());
  

这段代码的关键部分是reactRootView.setIsFabric(true)为这个 Activity 启用新的渲染器。

您现在可以通过运行您的 android 应用程序来验证一切是否正常:

yarn react-native run-android

在您的 Metro 终端日志中,您现在将看到以下日志以确认 Fabric 正在正确运行:

BUNDLE ./App.js
LOG Running "App" with "fabric":true,"initialProps":,"rootTag":1

迁移 Android

首先,确保您按照在您的 Android 应用程序中启用新渲染器 (Fabric)的说明进行操作。此外,我们还将假设您遵循了在您的 Android 应用程序中启用新的 NativeModule 系统 (TurboModule) 中的说明,因为 Makefile ( Android.mk) 和其他原生构建设置步骤已在此处提供,此处不再重复。

JavaScript

  1. 按照为新的 React Native Renderer (Fabric) 准备 JavaScript 代码库,确保您的其他 JS 更改已准备就绪
  2. 将调用替换requireNativeComponent为codegenNativeComponent。这告诉 JS 代码生成器开始生成组件的本机实现,包括 C++ 和 Java 类。这是它查找 WebView 组件的方式:
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';

// babel-plugin-codegen will replace the function call to use NativeComponentRegistry
// 'RCTWebView' is interopped by RCTFabricComponentsPlugins

export default (codegenNativeComponent<NativeProps>(
  'RCTWebView',
): HostComponent<NativeProps>);
  1. [Flow 用户]确保您的原生组件的 props 具有 Flow 类型,因为 JS 代码生成器使用这些类型来生成组件的类型安全的原生实现。codegen 在构建期间生成 C++ 类,这保证了本机实现始终与其 JS 接口保持同步。使用这些 c++ 兼容类型。
RNTMyNativeViewNativeComponent.js
import type Int32 from 'react-native/Libraries/Types/CodegenTypes';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type HostComponent from 'react-native';
import type ViewProps from 'react-native/Libraries/Components/View/ViewPropTypes';

type NativeProps = $ReadOnly<|
  ...ViewProps, // This is required.
  someNumber: Int32,
|>;

[...]

export default (codegenNativeComponent<NativeProps>(
  'RNTMyNativeView',
): HostComponent<NativeProps>);
  1. [TypeScript 用户]我们目前正在调查对 TypeScript 的支持。

本机/Java

  1. 更新(或创建)您的 ViewManager 以使用 Codegen 中生成的类。

具体来说,您必须实现生成的ViewManagerInterface并将事件传递给生成的ViewManagerDelegate。 你的 ViewManager 可以遵循这个结构。本示例中的 MyNativeView 类是一个 Android View 实现(类似于 LinearLayout、Button、TextView 等的子类)

MyNativeViewManager.java
// View manager for MyNativeView components.
@ReactModule(name = MyNativeViewManager.REACT_CLASS)
public class MyNativeViewManager extends SimpleViewManager<MyNativeView>
        implements RNTMyNativeViewManagerInterface<MyNativeView> 

  public static final String REACT_CLASS = "RNTMyNativeView";

  private final ViewManagerDelegate<MyNativeView> mDelegate;

  public MyNativeViewManager() 
    mDelegate = new RNTMyNativeViewManagerDelegate<>(this);
  

  @Nullable
  @Override
  protected ViewManagerDelegate<MyNativeView> getDelegate() 
    return mDelegate;
  

  @NonNull
  @Override
  public String getName() 
    return REACT_CLASS;
  

  @NonNull
  @Override
  protected MyNativeView createViewInstance(@NonNull ThemedReactContext reactContext) 
    return new MyNativeView(reactContext);
  

  1. 将您的 ViewManager 添加到您的应用程序加载的包之一。

具体在ReactNativeHost, updategetPackages方法里面要包括以下内容:

public class MyApplication extends Application implements ReactApplication 

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) 
    @Override
    public boolean getUseDeveloperSupport()  /* ... */ 

    @Override
    protected List<ReactPackage> getPackages() 
      List<ReactPackage> packages = new PackageList(this).getPackages();

      // ... other packages or `TurboReactPackage added` here...

      // Add those lines.
      packages.add(new ReactPackage() 
        @NonNull
        @Override
        public List<NativeModule> createNativeModules(
            @NonNull ReactApplicationContext reactContext) 
          return Collections.emptyList();
        

        @NonNull
        @Override
        public List<ViewManager> createViewManagers(
            @NonNull ReactApplicationContext reactContext) 
          // Your ViewManager is returned here.
          return Collections.singletonList(new MyNativeViewManager());
        
      );
      return packages;
    
  ;

  1. 添加 Fabric 组件注册表

您需要创建一个新的组件注册表,它允许您注册要被 Fabric 发现的组件。让我们创建MyComponents Registry具有以下内容的文件。

如您所见,native()我们将在下一段中用 C++ 实现一些方法。

package com.awesomeproject;

import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.fabric.ComponentFactory;
import com.facebook.soloader.SoLoader;

@DoNotStrip
public class MyComponentsRegistry 
  static 
    SoLoader.loadLibrary("fabricjni");
  

  @DoNotStrip private final HybridData mHybridData;

  @DoNotStrip
  private native HybridData initHybrid(ComponentFactory componentFactory);

  @DoNotStrip
  private MyComponentsRegistry(ComponentFactory componentFactory) 
    mHybridData = initHybrid(componentFactory);
  

  @DoNotStrip
  public static MyComponentsRegistry register(ComponentFactory componentFactory) 
    return new MyComponentsRegistry(componentFactory);
  

  1. 注册您的自定义 Fabric 组件注册表

最后,让我们编辑getJSIModulePackagefromReactNativeHost以将您的 Component Registry 与 Core 一起注册:

public class MyApplication extends Application implements ReactApplication 

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) 
    @Nullable
    @Override
    protected JSIModulePackage getJSIModulePackage() 
      return new JSIModulePackage() 
        @Override
        public List<JSIModuleSpec> getJSIModules(
                final ReactApplicationContext reactApplicationContext,
                final JavaScriptContextHolder jsContext) 
          final List<JSIModuleSpec> specs = new ArrayList<>();
          specs.add(new JSIModuleSpec() 
            // ...

            @Override
            public JSIModuleProvider<UIManager> getJSIModuleProvider() 
              final ComponentFactory componentFactory = new ComponentFactory();
              CoreComponentsRegistry.register(componentFactory);

              // Add this line just below CoreComponentsRegistry.register
              MyComponentsRegistry.register(componentFactory);

              // ...
            
          );
          return specs;
        
      ;
    
  ;

本机/C++

现在是时候为你MyComponentsRegistry的 C++ 提供一个实现了:

  1. 创建头文件:MyComponentsRegistry.h

该文件应放在src/main/jni文件夹内。请注意,kJavaDescriptor应该根据您为项目选择的包名称进行调整。

MyComponentsRegistry.h
#pragma once

#include <ComponentFactory.h>
#include <fbjni/fbjni.h>
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h>

namespace facebook 
namespace react 

class MyComponentsRegistry
    : public facebook::jni::HybridClass<MyComponentsRegistry> 
  public:
  constexpr static auto kJavaDescriptor =
      "Lcom/awesomeproject/MyComponentsRegistry;";

  static void registerNatives();

  MyComponentsRegistry(ComponentFactory *delegate);

  private:
  friend HybridBase;

  static std::shared_ptr<ComponentDescriptorProviderRegistry const>
  sharedProviderRegistry();

  const ComponentFactory *delegate_;

  static jni::local_ref<jhybriddata> initHybrid(
      jni::alias_ref<jclass>,
      ComponentFactory *delegate);
;

 // namespace react
 // namespace facebook
  1. 创建一个实现文件:MyComponentsRegistry.cpp

该文件应放置在src/main/jni`MyComponentsRegistry.h 旁边的文件夹中

我的组件注册表.cpp

#include "MyComponentsRegistry.h"

#include <CoreComponentsRegistry.h>
#include <fbjni/fbjni.h>
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <react/renderer/components/rncore/ComponentDescriptors.h>
#include <react/renderer/components/samplelibrary/ComponentDescriptors.h>

namespace facebook 
namespace react 

MyComponentsRegistry::MyComponentsRegistry(
    ComponentFactory *delegate)
    : delegate_(delegate) 

std::shared_ptr<ComponentDescriptorProviderRegistry const>
MyComponentsRegistry::sharedProviderRegistry() 
  auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry();

  providerRegistry->add(concreteComponentDescriptorProvider<
                        RNTMyNativeViewComponentDescriptor>());

  return providerRegistry;


jni::local_ref<MyComponentsRegistry::jhybriddata>
MyComponentsRegistry::initHybrid(
    jni::alias_ref<jclass>,
    ComponentFactory *delegate) 
  auto instance = makeCxxInstance(delegate);

  auto buildRegistryFunction =
      [](EventDispatcher::Weak const &eventDispatcher,
          ContextContainer::Shared const &contextContainer)
      -> ComponentDescriptorRegistry::Shared 
    auto registry = MyComponentsRegistry::sharedProviderRegistry()
                        ->createComponentDescriptorRegistry(
                            eventDispatcher, contextContainer);

    auto mutableRegistry =
        std::const_pointer_cast<ComponentDescriptorRegistry>(registry);

    mutableRegistry->setFallbackComponentDescriptor(
        std::make_shared<UnimplementedNativeViewComponentDescriptor>(
            ComponentDescriptorParameters
                eventDispatcher, contextContainer, nullptr));

    return registry;
  ;

  delegate->buildRegistryFunction = buildRegistryFunction;
  return instance;


void MyComponentsRegistry::registerNatives() 
  registerHybrid(
      makeNativeMethod("initHybrid", MyComponentsRegistry::initHybrid),
  );


 // namespace react
 // namespace facebook
  1. 在 OnLoad.cpp 中加载您的文件

如果您按照 TurboModule 说明进行操作,则该文件夹中应该有一个OnLoad.cpp文件src/main/jni。在那里你应该添加一行来加载MyComponentsRegistry类:

OnLoad.cpp
#include <fbjni/fbjni.h>
#include "MyApplicationTurboModuleManagerDelegate.h"
// Add this import
#include "MyComponentsRegistry.h"

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) 
  return facebook::jni::initialize(vm, [] 
    facebook::react::MyApplicationTurboModuleManagerDelegate::registerNatives();

    // Add this line
    facebook::react::MyComponentsRegistry::registerNatives();
  );

您现在可以通过运行您的 android 应用程序来验证一切是否正常:

yarn react-native run-android

以上是关于在 Android 上启用 Fabric的主要内容,如果未能解决你的问题,请参考以下文章

HyperLeger Fabric SDK开发——ledger

您可以在多大程度上自定义 Fabric 的 Digits 在 Android 上的流程、外观和感觉?

如何为Fabric.js启用响应式设计

fabric之使用传输层安全性(TLS)保护通信安全

Hyperledger Fabric启用CouchDB为状态数据库

分享帖子后,twitter 中是不是有使用 android 中的 fabric 的回调方法?