在 Android 上启用 Fabric

8 篇文章 0 订阅

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值