在 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
- 按照为新的 React Native Renderer (Fabric) 准备 JavaScript 代码库,确保您的其他 JS 更改已准备就绪
- 将调用替换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>);
- [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>);
- [TypeScript 用户]我们目前正在调查对 TypeScript 的支持。
本机/Java
- 更新(或创建)您的 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);
- 将您的 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;
;
- 添加 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);
- 注册您的自定义 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++ 提供一个实现了:
- 创建头文件: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
- 创建一个实现文件: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
- 在 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 上的流程、外观和感觉?