React Native 新架构适配之 Android 迁移 Fabric Native Components 指南
最近 React Native 团队发布了 react native 0.76 稳定版,各位小伙伴有没有升级上来呢?新架构从 2018 年开始说要弄新架构到现在已经五六年了,现在终于也是在这个版本 默认启用新架构 了。
新架构在性能上提升还是很大的,也有很多值得我们关注的地方。当然完整的新架构其实包含了很多部分,比如说原生组件渲染和刷新的机制、原生与 JS 层的通讯、新架构中支持 Native 与 JS 内存交换避免 Bridge 的数据序列化和反序列化带来的性能损耗、还有跨线程工作等等,感兴趣的小伙伴可以看看这篇文章 React Native New Architecture is here。当然后续计划中还有很多有意思的功能在开发,总的来说就是快,更快,超级快。
不过话要说回来,如果你发现自己把版本升级上去并没有很明显的性能提升这是正常情况,因为现在大部分依赖库都还没有适配新架构,整个社区的适配工作是需要不少时间的。我们团队几年前开源了 react-native-ad 聚合广告变现模块,能够帮助开发者快速对接穿山甲、百度广告联盟、腾讯优量汇、快手广告平台等多家主要流量变现平台。
因为之前已经重构了好几个版本各种适配代码混合在一起,后续维护也越来越麻烦了。所以这次我们直接就打算在新架构的基础上完全重构一个聚合广告库 react-native-gromore (React Native GroMore 是穿山甲 GroMore SDK 的 React Native 的实现,GroMore SDK 是一个聚合广告 SDK 现已支持穿山甲、Abmob、百度、优量汇、游可赢、快手、Mintegral、Sigmob、unity 等广告平台的聚合对接,如果有相关需求的小伙伴可以联系我们对接) 。
虽然说是基于 react native 新架构开发的,但是现在还是有很多用户在低版本 react native 需要使用的,那怎么办呢?当然 rn 团队也是考虑到这种情况了的,所以并没有一刀切的废弃全部的旧架构接口,而是允许开发者做适配,所以我们在 react-native-gromore 中也是完全适配了新旧架构并且对外提供统一的 API 也就是说,后续能够直接无感升级 react native 新架构。
有的小伙伴可能看过我们前不久写的一篇 React Native 新架构适配之 IOS 迁移 Fabric Native Components 指北 ,那么这篇博客就来和大家分享分享新架构 Android 部分适配。
React Native Codegen 接口声明
首先就是 JavaScript(Typescript)层,在旧架构中组件的定义和参数传递约束性其实是比较低的,几乎没有什么很强的定义映射,在旧架构中通常使用 requireNativeComponent
接口导出原生层实现的 Native Components 组件。(当然这个部分与 iOS 中基本上是差不多的,如果看过我们上一篇博客的小伙伴可以跳过这个部分)
在新架构中则是引入了一个“新概念” Codegen,简单来说就是可以先定义 Typescript 的 Fabric Native Components 接口部分,然后由 React Native Codegen 首先生成 C++ 接口定义,随后库作者实现相应接口即可这样就能够在一定程度上保证接口的约束性关系。当然 Android 部分由于 Java 层和 C++ 的互调用还是需要走 JNI 所以除了 C++ 的接口部分之外还生成了 Java 与 C++ 之间的一些 JNI 桥接代码。
通过下列代码可以对比出来新旧架构层在 Typescript(目前 Codegen 暂时仅支持 Flow 或 TypeScript 定义用于定义接口)的定义上区别
// 旧架构
import React from 'react';
import { requireNativeComponent, ViewStyle } from 'react-native';
const FeedAdComponent = requireNativeComponent('FeedAd');
export interface FeedAdProps {
codeid: string;
style?: ViewStyle;
onAdError?: Function;
}
const TxFeedAd = (props: FeedAdProps) => {
return (
<FeedAdComponent
codeid={props.codeid}
style={props.style}
onAdError={props.onAdError}
/>
)
}
// 新架构
import type { ViewProps } from 'react-native';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type {
DirectEventHandler,
Int32,
} from 'react-native/Libraries/Types/CodegenTypes'; // https://github.com/reactwg/react-native-new-architecture/discussions/27
export type AdFailWithErrorEventReply = Readonly<{
code: Int32;
message: string;
}>;
interface FeedViewProps extends ViewProps {
codeId: string;
onAdError?: DirectEventHandler<
Readonly<AdFailWithErrorEventReply>
>; // 广告加载、渲染失败
}
export default codegenNativeComponent<FeedViewProps>('FeedView');
通过上面 react-native-ad 中 Feed 广告的重构部分代码摘录就能看出来,首先旧架构中 requireNativeComponent 获取到的原生对象其实是一个 any 类型的 Comment 所以在导出组件时,通常需要另外定义一个用于导出合理类型声明的函数组件套用。而新架构上的话 codegenNativeComponent 直接通过定义类型泛型能够直接导出指定 props 类型的 Comment 组件。
其次,能够看出来新架构这边是更需要规范定义 props 参数类型的如回调函数类型需要使用 DirectEventHandler 或者 EventHandler 泛型定义,而在旧架构中对类型定义就比较随意定义了一个 Function 类型,除此之外细心的小伙伴们可能发现了在回调函数中的参数我这边用到了 Int32 这个类型,前端的小伙伴可能对这个类型就比较陌生了,还记得我们上面说到的 Codegen 会通过我们这里的 Typescript 定义的代码生成 C++ 接口代码吗?是的你没猜错,这里 Int32 就是对应 C++ 中的 Int32 数据类型,而在 Java 中会被映射为 double,因此接口层定义肯定是不支持全部的 JS 类型的,仅支持部分数据类型映射(这里可以参考官方文档)
当然,除了通过 Typescript 接口定义之外,还需要配置 Codegen(这边指的是旧的库项目中直接准备升级的话,如果是通过 react-native-bob 创建的新依赖库的话会默认配置好的)首先文件名是有规范性的,这是为了方便 Codegen 能够识别哪些 ts 代码文件需要生成 NativeSpec(C++ 接口定义代码)要求如下:
1、该文件必须命名为 <MODULE_NAME>NativeComponent
,使用 Flow 时带有 .js
或 .jsx
扩展名,或者 .ts
或 .tsx
2、该文件必须导出 HostComponent
对象
完成这些之后,以上面的 FeedView 广告组件为例,我们目前的文件夹结构应该如下
.
├── android
├── ios
├── package.json
├── src
│ ├── FeedViewNativeComponent.ts
│ └── index.tsx
├── tsconfig.json
└── yarn.lock
定义文件符合规范后,就是在 package.json 中配置 codegenConfig
部分了,其中 name
配置库的名称(可以简单理解为生成代码前缀部分),type
表示生成的代码类型(目前改参数有 components
、modules
、 all
三个类型分别代表 Fabric Native Components、 Turbo Native Modules 和包含两种类型的全部),jsSrcsDir
为 Codegen 解析的 js
规范代码文件的相对路径。
{
"name": "react-native-ad",
"version": "1.0.0",
"description": "This is an aggregate advertising package.",
"private": true,
"main": "lib/commonjs/index",
"module": "lib/module/index",
"types": "lib/typescript/src/index.d.ts",
"react-native": "src/index",
"source": "src/index",
……
"codegenConfig": {
"name": "RCTAdViewSpec",
"type": "all",
"jsSrcsDir": "src"
}
}
配置 Android Gradle 部分
在依赖库的项目 android/build.gradle
中添加如下配置项
buildscript {
ext.safeExtGet = {prop, fallback ->
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}
repositories {
google()
gradlePluginPortal()
}
dependencies {
classpath("com.android.tools.build:gradle:7.0.4")
}
}
// 增加判断是否启用新架构和获取全部架构函数定义
def reactNativeArchitectures() {
def value = rootProject.getProperties().get("reactNativeArchitectures")
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
}
def isNewArchitectureEnabled() {
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
}
def supportsNamespace() {
def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
def major = parsed[0].toInteger()
def minor = parsed[1].toInteger()
// Namespace support was added in 7.3.0
return (major == 7 && minor >= 3) || major >= 8
}
apply plugin: 'com.android.library'
// 判断是否启用新架构,增加 com.facebook.react 插件
if (isNewArchitectureEnabled()) {
apply plugin: "com.facebook.react"
}
android {
compileSdkVersion safeExtGet('compileSdkVersion', 31)
defaultConfig {
minSdkVersion safeExtGet('minSdkVersion', 21)
targetSdkVersion safeExtGet('targetSdkVersion', 31)
}
// 增加根据不同命名空间使用不同 AndroidManifest
if (supportsNamespace()) {
namespace "com.rnad"
sourceSets {
main {
manifest.srcFile "src/main/AndroidManifestNew.xml"
}
}
}
// 增加 sourceSets 部分
sourceSets {
main {
resources {
srcDirs 'src/main/resources'
}
if (isNewArchitectureEnabled()) {
java.srcDirs += [
"src/newarch",
// This is needed to build Kotlin project with NewArch enabled
"${project.buildDir}/generated/source/codegen/java"
]
} else {
java.srcDirs += ["src/oldarch"]
}
}
}
}
repositories {
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$projectDir/../node_modules/react-native/android"
}
mavenCentral()
google()
}
dependencies {
implementation 'com.facebook.react:react-native:+'
}
// 添加 react native codegen 代码配置
if (isNewArchitectureEnabled()) {
react {
jsRootDir = file("../src/")
libraryName = "RCTAdView"
codegenJavaPackageName = "com.rnad"
}
}
能够看到上面第一个部分就是增加了 reactNativeArchitectures、isNewArchitectureEnabled 和 supportsNamespace 定义。
然后通过 isNewArchitectureEnabled 函数判断是否开启新架构,启用新架构的话会增加一个 com.facebook.react gradle 插件的引入。
在 android 部分配置中能够通过 supportsNamespace 判断所依赖的应用程序是否支持命名空间功能,支持的情况下能够直接使用新架构单独的 AndroidManifest.xml 配置否则就和旧架构使用相同的,同时还通过 sourceSets 配置项,判断引入库的应用程序是否使用新架构,如果使用新架构的话将 Java 或者 Kotlin 部分代码应用 src/newarch 部分代码否则将应用 src/oldarch 中的实现代码,当然如果是新旧架构共用的代码部分就直接写到 src/main 中(能够看到 android 和 iOS 部分还是有差异的,在 iOS 中适配主要依赖宏定义在同一个代码文件中,在 android 部分中主要还是依赖 gradle 编译不同源代码文件)。
最后判断启用了新架构的话,配置 com.facebook.react gradle 插件。
实现 RNADFeedView 组件及属性获取
按照惯例我还是贴一下现在 android 部分的代码组成目录结构
能够看到,组件的注册还是没有变化的有一个 GromoreViewPackage.kt 文件,在里面可以注册实现好的 fabric component 和 turbo modules,然后为了能够使 RNADFeedView 组件同时兼容旧架构和适配新架构,这里我们需要在分别的文件夹 newarch 和 oldarch 中实现一个 RNADFeedViewManagerSpec 类,在 main 中实现 RNADFeedViewManager 管理类和 RNADFeedView 组件,最后 GromoreViewPackage 中注册 RNADFeedViewManagerSpec 来实现不同架构会调用不同实现代码。
让我们一步一步来实现它,首先看看 RNADFeedView 的实现
package com.rnad
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import com.facebook.react.bridge.ReactContext
import com.rnad.RNADFeedViewManager
class RNADFeedView(val context: ReactContext) :
RelativeLayout(context) {
val TAG = RNADFeedViewManager.NAME
var _view: View? = null
var _codeId: String? = null
fun setCodeId(value: String?) {
// Log.d(TAG, "setCodeId: value:$value")
if (value == null) return
_codeId = value
// TODO:: init sdk
// add view
_view = View(context)
addView(_view)
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b)
Log.d(
TAG,
"onLayout<$id>: ${width}/$height"
)
// 当组件更新宽高或位置时可以在这个回调中刷新
}
}
能够看到,我们的组件是继承于 RelativeLayout 的一个组件,并且覆盖实现了 onLayout 函数,除此之外还定义了一个 setCodeId 函数用于设置广告位 id 也就是接收我们在 JS 层定义的 codeId 属性的。
定义好 View 组件后,还需要一个统一的 RNADFeedViewManager 实现,
package com.rnad
import android.util.Log
import android.view.View
import android.view.ViewGroup
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.SimpleViewManager
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.annotations.ReactProp
@ReactModule(name = RNADFeedViewManager.NAME)
abstract class RNADFeedViewManager(
private val mContext: ReactApplicationContext
) : SimpleViewManager<RNADFeedView>() {
companion object {
const val NAME = "RNADFeedView"
}
override fun getName(): String {
return NAME
}
override fun createViewInstance(context: ThemedReactContext): RNADFeedView {
return RNADFeedView(context)
}
@ReactProp(name = "codeId")
fun setCodeId(view: RNADFeedView?, value: String?) {
Log.d(NAME, "setCodeId: value:$value")
if (value == null) return
view?.setCodeId(value)
}
}
在 RNADFeedViewManager 中能够看到我们熟悉的 getName 函数用于声明组件名称和 @ReactProp 属性注解,以及 setCodeId 函数的声明,当然还有新架构中引入的 @ReactModule 组件名注解,其他部分和之前声明 ViewManager 大致相同,在 createViewInstance 函数中我们实例化 RNADFeedView 组件。
旧架构 RNADFeedViewManagerSpec 实现
package com.rnad
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.annotations.ReactModule
@ReactModule(name = RNADFeedViewManager.NAME)
class RNADFeedViewManagerSpec(val context: ReactApplicationContext) :
RNADFeedViewManager(context) {
}
是的,其实在旧架构中我们只需要将 RNADFeedViewManagerSpec 继承于 RNADFeedViewManager 就行了,因为属性获取的函数和注解我们已经在 RNADFeedViewManager 中实现了,模块名的获取函数也实现了。
新架构 RNADFeedViewManagerSpec 实现
package com.rnad
import android.util.Log
import android.widget.RelativeLayout
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.ViewManagerDelegate
import com.facebook.react.viewmanagers.RNADFeedViewManagerDelegate
import com.facebook.react.viewmanagers.RNADFeedViewManagerInterface
class RNADFeedViewManagerSpec(val mContext: ReactApplicationContext) :
RNADFeedViewManager(mContext),
RNADFeedViewManagerInterface<RNADFeedView> {
private val mDelegate = RNADFeedViewManagerDelegate(this)
override fun getDelegate(): ViewManagerDelegate<RNADFeedView>? {
return mDelegate
}
}
在新架构中 RNADFeedViewManagerSpec 同样也是继承了父类 RNADFeedViewManager 模块名声明也是在父类声明的,除此之外这里还有额外实现了一个 RNADFeedViewManagerInterface 接口,这是一个什么东西呢?还记得我们上面说 codegen 会生成 C++ 接口声明和 JNI 桥接代码吗,这里的 com.facebook.react.viewmanagers.RNADFeedViewManagerInterface 和 com.facebook.react.viewmanagers.RNADFeedViewManagerDelegate 就是 codegen 生成出来的桥接代码部分,这部分代码可以在 android/build/generated/source/codegen
文件夹中找到,点击进去我们能看到如下代码部分
// RNADFeedViewManagerDelegate.java
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GeneratePropsJavaDelegate.js
*/
package com.facebook.react.viewmanagers;
import android.view.View;
import androidx.annotation.Nullable;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.BaseViewManagerInterface;
public class RNADFeedViewManagerDelegate<T extends View, U extends BaseViewManagerInterface<T> & RNADFeedViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public RNADFeedViewManagerDelegate(U viewManager) {
super(viewManager);
}
@Override
public void setProperty(T view, String propName, @Nullable Object value) {
switch (propName) {
case "codeId":
mViewManager.setCodeId(view, value == null ? null : (String) value);
break;
default:
super.setProperty(view, propName, value);
}
}
}
// RNADFeedViewManagerInterface.java
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GeneratePropsJavaInterface.js
*/
package com.facebook.react.viewmanagers;
import android.view.View;
import androidx.annotation.Nullable;
public interface RNADFeedViewManagerInterface<T extends View> {
void setCodeId(T view, @Nullable String value);
}
最后在 RNADFeedViewManagerSpec 中实例化一个 RNADFeedViewManagerDelegate 对象,并覆盖父类 getDelegate 方法返回 Delegate 实例新架构的适配就基本搞定了,当然要注意 RNADFeedViewManager 中实现的 codeId 属性接受方法需要和 Interface 文件中的 setCodeId 相同这样就在一个函数中既实现了旧架构的属性获取和新架构的属性配置。
最后将 RNADFeedViewManagerSpec 注册到 RCTAdViewPackage 中就可以了
package com.rnad
import com.facebook.react.ReactPackage
import com.facebook.react.TurboReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.module.model.ReactModuleInfoProvider
import com.facebook.react.uimanager.ViewManager
import kotlin.collections.ArrayList
class RCTAdViewPackage : ReactPackage {
companion object {
var mApplicationContext: ReactApplicationContext? = null
}
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
mApplicationContext = reactContext
val viewManagers: MutableList<ViewManager<*, *>> = ArrayList()
viewManagers.add(RNADFeedViewManagerSpec(reactContext))
return viewManagers
}
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
val modules = ArrayList<NativeModule>()
return modules
}
}
到这里,一个非常基础的 View 组件就完成了它的新旧架构的实现,并且我们也能够获取到 React Native JavaScript 层定义的属性了。但是博客显然到这里还没有结束,我们还有回调事件没有适配呢,那么如何适配新旧俩个架构的组件回调事件呢?继续看下去吧。
组件 RNADFeedView 回调事件适配
如果按照我们在 iOS 的适配逻辑来说,在 Delegate 文件中应该会有一个和 js 那边定义事件相同的函数文件才对,但是我们能看到上面生成出来的 RNADFeedViewManagerDelegate 代码中并没有发现我们定义的 onAdError 事件函数对吧?实际上 codegen 生成出来的 cpp 代码 EventEmitters.h 中是有相对应的函数回调事件的,但是在 JNI 代码文件中目前确实还没有相对应的函数代码生成(应该是还没完成后续版本应该会迭代上来),所以我们这边需要用到目前 React Native 团队提供的事件发送适配层。
首先在我们代码中定义一个 RNADViewBaseEvent 基础事件的包装类(当然我这里也只是为了方便使用所以封装了一下,你也可以直接在代码里实例化并且直接调用),具体代码如下
package com.rnad.events
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.events.Event
class RNADViewBaseEvent(
surfaceId: Int,
viewTag: Int,
val EVENT_NAME: String,
val args: WritableMap?
) : Event<RNADViewBaseEvent>(surfaceId, viewTag) {
override fun getEventName(): String = EVENT_NAME
override fun getEventData(): WritableMap? = args
}
然后在需要发送事件的 RNADFeedView 组件中增加一个 sendEvent 事件发送函数,如下
package com.rnad
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.WritableNativeMap
import com.facebook.react.uimanager.UIManagerHelper
import com.rnad.events.RNADViewBaseEvent
import com.rnad.RNADFeedViewManager
class RNADFeedView(val context: ReactContext) :
RelativeLayout(context) {
val TAG = RNADFeedViewManager.NAME
var _view: View? = null
var _codeId: String? = null
fun setCodeId(value: String?) {
// Log.d(TAG, "setCodeId: value:$value")
if (value == null) return
_codeId = value
// TODO:: init sdk
// add view
_view = View(context)
addView(_view)
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b)
Log.d(
TAG,
"onLayout<$id>: ${width}/$height"
)
// 当组件更新宽高或位置时可以在这个回调中刷新
}
fun sendEvent(name: String, args: WritableMap? = WritableNativeMap()) {
val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, id)
val surfaceId: Int = UIManagerHelper.getSurfaceId(this)
dispatcher?.dispatchEvent(
RNADViewBaseEvent(surfaceId, id, name, args)
)
}
fun onError(code: Int, msg: String) {
val data = WritableNativeMap()
data.putInt("code", code)
data.putString("message", msg)
sendEvent("onAdError", data)
}
}
为了方便回调事件在 RNADFeedView 中统一定义了一个 sendEvent 函数,接受回调事件名和回调参数两个入参,在函数中通过 UIManagerHelper 获取到 dispatcher 实例,然后利用我们构造的 RNADViewBaseEvent 对象实例化一个事件,并通过 dispatcher 发送回 JavaScript 层。
最后通过调用 sendEvent("onAdError", data) 函数就能够实现我们事件的回调了(注意这里的事件名需要和 js 中定义的回调事件名相同)。
实际上 React Native 团队在这里的 dispatcher 事件调度器能够实现新旧架构的事件回调,不过旧架构中我们需要先在 ViewManager 中注册回调事件,具体代码 RNADFeedViewManager 如下
package com.rnad
import android.util.Log
import android.view.View
import android.view.ViewGroup
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.SimpleViewManager
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.react.bridge.WritableMap
import com.facebook.react.common.MapBuilder
@ReactModule(name = RNADFeedViewManager.NAME)
abstract class RNADFeedViewManager(
private val mContext: ReactApplicationContext
) : SimpleViewManager<RNADFeedView>() {
companion object {
const val NAME = "RNADFeedView"
}
override fun getName(): String {
return NAME
}
override fun createViewInstance(context: ThemedReactContext): RNADFeedView {
return RNADFeedView(context)
}
@ReactProp(name = "codeId")
fun setCodeId(view: RNADFeedView?, value: String?) {
Log.d(NAME, "setCodeId: value:$value")
if (value == null) return
view?.setCodeId(value)
}
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
val events = MapBuilder.builder<String, Any>()
for (item in ["onAdError"]) {
events.put(item, MapBuilder.of("registrationName", item))
}
return events.build()
}
}
在 ViewManager 中覆盖实现 getExportedCustomDirectEventTypeConstants 函数,并且将我们组件全部的回调函数注册上去就可以了,至此就能愉快的给 RN 层回调事件了。
当然在新架构中除了用 ObjectC and Swift、Java and Kotlin 去实现 React Native 包之外,其实原汁原味的 cpp 实现跨平台依赖包应该会更丝滑了(我也在想一个很“邪恶” golang cgo + cpp 给 rn 提供跨平台 native 功能包的想法,有个团队好像已经用 rust + cpp -> rn module 流程跑通了)。
感谢你看到这里,如果有问题欢迎给我博客 https://bin.zmide.com/?p=1268 留言回复。