RN 调用原生安卓/iOS 方法、原生回调RN
·
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
1. RN 调用 Android 原生方法
例如 RN 调用 Android 获取设备信息。
Android 创建 Module
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())
2. RN JS 调用 Android
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()
3. iOS 原生暴露方法给 RN
Swift 示例:
创建 Native Module
@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)
)
@end
RN 调用方式和 Android 一样:
DeviceModule.getDeviceName()
.then(console.log)
4. 原生主动回调 RN
例如:
-
支付结果通知
-
蓝牙扫描结果
-
GPS位置变化
-
推送消息
-
登录状态变化
这种不是 RN 调原生,而是:
Native
|
|
EventEmitter
|
|
React Native JS
Android 回调 RN
原生发送事件
reactContext
.getJSModule(
DeviceEventManagerModule.RCTDeviceEventEmitter::class.java
)
.emit(
"onLogin",
"success"
)
JS监听
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 listener
5. iOS 回调 RN
Objective-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)
});
6. Promise vs Callback vs Event
RN 原生通信常见三种:
| 方式 | 方向 | 场景 |
|---|---|---|
| Promise | JS → Native → JS | 一次性结果 |
| Callback | JS → Native → JS | 旧方式 |
| EventEmitter | Native → JS | 持续事件 |
例如:
获取电量
Promise:
RN
|
getBattery()
|
Native
|
return 80%
适合。
蓝牙扫描
Event:
Native
发现设备1
|
emit
发现设备2
|
emit
发现设备3
适合。
7. 新架构 Fabric / TurboModule 下
你之前问过 RN Fabric,这里关联:
旧架构:
JS
|
Bridge(JSON)
|
Native
性能瓶颈:
-
JSON序列化
-
异步消息队列
新架构:
JS
|
JSI
|
C++层
|
TurboModule
|
Native
特点:
-
不经过 JSON Bridge
-
可以同步调用
-
类型安全
-
性能更高
例如:
旧:
NativeModules.Device.getName()
↓
Bridge消息
新:
JS
|
JSI Function
|
C++
|
Kotlin/Swift
8. 实际项目结构
比如微信扫码登录:
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
更多推荐
所有评论(0)