React Native(RN)调用原生 Android/iOS 方法,以及原生回调 RN,核心机制是 Native Module(原生模块)+ Bridge/JSI 通信。
整体流程:
JavaScript (RN) | | Native Module 调用 | --------------------- | | Android Native iOS Native (Java/Kotlin) (Obj-C/Swift) | | | | 系统能力/API 系统能力/API例如 RN 调用 Android 获取设备信息。
Kotlin 示例:
class DeviceModule(
reactContext: ReactApplicationContext
) : ReactContextBaseJavaModule(reactContext) {
override fun getName(): String {
return "DeviceModule"
}
@ReactMethod
fun getDeviceName(promise: Promise) {
val name = Build.MODEL
promise.resolve(name)
}
}
注册:
class MyPackage : ReactPackage {
override fun createNativeModules(
context: ReactApplicationContext
): List<NativeModule> {
return listOf(
DeviceModule(context)
)
}
}
加入:
packages.add(MyPackage())
JS:
import {
NativeModules
} from 'react-native';
const {DeviceModule} = NativeModules;
DeviceModule.getDeviceName()
.then(name=>{
console.log(name)
});
调用链:
JS | | DeviceModule.getDeviceName() |Bridge |Android Module |promise.resolve() |Bridge |JS Promise.then()Swift 示例:
@objc(DeviceModule)
class DeviceModule: NSObject {
@objc
func getDeviceName(
_ resolve:RCTPromiseResolveBlock,
rejecter reject:RCTPromiseRejectBlock
){
let name =
UIDevice.current.name
resolve(name)
}
@objc
static func requiresMainQueueSetup()
-> Bool {
return false
}
}
暴露:
#import <React/RCTBridgeModule.h>@interface RCT_EXTERN_MODULE(DeviceModule,NSObject)RCT_EXTERN_METHOD(getDeviceName:resolver:(RCTPromiseResolveBlock)rejecter:(RCTPromiseRejectBlock))@endRN 调用方式和 Android 一样:
DeviceModule.getDeviceName()
.then(console.log)
例如:
这种不是 RN 调原生,而是:
Native | |EventEmitter | |React Native JSreactContext
.getJSModule(
DeviceEventManagerModule.RCTDeviceEventEmitter::class.java
)
.emit(
"onLogin",
"success"
)
import {
NativeEventEmitter,
NativeModules
} from 'react-native';
const emitter =
new NativeEventEmitter(
NativeModules.DeviceModule
);
const sub =
emitter.addListener(
"onLogin",
data=>{
console.log(data)
}
);
收到:
Android emit("onLogin") | | RN JS listenerObjective-C:
#import <React/RCTEventEmitter.h>@interface DeviceModule:RCTEventEmitter@end发送:
[self sendEventWithName: @"onLogin" body:@{ @"status":@"success" }];JS:
const emitter =
new NativeEventEmitter(
NativeModules.DeviceModule
);
emitter.addListener(
"onLogin",
data=>{
console.log(data)
});
RN 原生通信常见三种:
例如:
Promise:
RN |getBattery() |Native |return 80%适合。
Event:
Native发现设备1 |emit发现设备2 |emit发现设备3适合。
你之前问过 RN Fabric,这里关联:
旧架构:
JS |Bridge(JSON) |Native性能瓶颈:
新架构:
JS |JSI |C++层 |TurboModule |Native特点:
例如:
旧:
NativeModules.Device.getName()
↓
Bridge消息
新:
JS |JSI Function |C++ |Kotlin/Swift比如微信扫码登录:
RN:
LoginModule.scanQRCode()
Native:
Android:
startCamera()
scan()
扫码成功:
emit(
"QRCodeResult",
{
code:"abc123"
}
)
RN:
listener(
data=>{
login(data.code)
}
)
流程:
RN点击登录 | |Native打开微信扫码 | |扫码完成 | |Native Event | |RN收到code | |请求服务器登录所以 RN 和原生通信可以总结为:
RN调用原生:NativeModules / TurboModule原生返回一次:Promise原生持续通知:EventEmitter新架构:JSI + TurboModule + Fabric如果你正在研究 RN Fabric 渲染流程 + JSI + TurboModule,下一步可以看 TurboModule 从 JS 到 Kotlin/Swift 的完整调用链源码流程。
