这两天由于公司移动方向的开发资源不足,所以决定接触一下一些跨平台的方案。由于Flutter暂时还没有 Release ,所以主要还是先依靠 React Native 来做一些页面。虽然 React Native 已经是非常成熟的技术了,但我第一次用还是遇到了问题,在此记录一下。
需求
因为 React Native 并不是完全脱离本地代码,而且也是集成进现有的项目,所以调用本地代码的需求比较大。需要在 iOS 和 Android 两方代码中都建立通道,才能在 React Native 中统一调用。
添加模块
https://reactnative.cn/docs/native-modules-ios/
https://reactnative.cn/docs/native-modules-android/
上面是 React Native 中文网的两个文档,iOS 端直接按照文档步骤添加完成就好,Android 则与文档之中的不同。
Android 添加自定义 Toast 模块
定义模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @ReactModule(name = "RNToast") public class ToastModule extends ReactContextBaseJavaModule {
public ToastModule(ReactApplicationContext reactContext) { super(reactContext); }
@Override public String getName() { return "RNToast"; }
@ReactMethod public void toast(final String msg) { ToastUtils.showCenterToast(msg, getReactApplicationContext()); }
}
|
与文档中不同的是增加了ReactModule的注解,主要参考了已有的 ToastAndroid 模块
定义 Package
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @ReactModuleList(nativeModules = { ToastModule.class }) public class ReactNativePackage extends LazyReactPackage {
@Override public List<ModuleSpec> getNativeModules(ReactApplicationContext reactContext) { return Arrays.asList( ModuleSpec.nativeModuleSpec( ToastModule.class, () -> new ToastModule(reactContext) // 此处是 Provider 接口实现 ) ); }
@Override public ReactModuleInfoProvider getReactModuleInfoProvider() { return LazyReactPackage.getReactModuleInfoProviderViaReflection(this); }
}
|
同样增加了 ReactModuleList 注解,以及使用了 LazyReactPackage 构建懒加载的 Package,主要参考了 MainReactPackage
添加 Package 到 RN 环境
1 2 3 4 5 6 7 8 9
| mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .addPackage(new ReactNativePackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build();
|
这块是初始化 ReactRootView 时的参数设置,只需要增加自定义的 Package。预先提供的内置 Module 都是这样提供的,必要时可以通过 MainPeactPackage 进入之后查看源码
与文档中不同的地方
文档写了需要放在指定的包名的 MainApplication 中,这个并不需要。只需要在 ReactInstanceManager 构建时增加自定义的 Package 就好。
这个 package 需要在MainApplication.java文件的getPackages方法中提供。这个文件位于你的 react-native 应用文件夹的 android 目录中。具体路径是: android/app/src/main/java/com/your-app-name/MainApplication.java