你提到"RN 原生交互 & 桥接 ",我理解你可能是在问 React Native(RN)如何和原生 Android/iOS 交互,以及 Bridge(桥接机制)怎么工作。下面从原理到实践梳理。
1. RN 和原生的关系
React Native 本质上是:
JavaScript/TypeScript 写业务逻辑 + 原生组件负责真正渲染和系统能力。
结构大致:
JS 层
React Components
|
| Bridge / JSI
|
Native 层
Android(Java/Kotlin)
iOS(Objective-C/Swift)
|
系统能力
Camera / GPS / Bluetooth / UI
RN 需要原生能力时,就通过桥接调用:
例如:
- • JS 调摄像头
- • JS 调支付 SDK
- • JS 调蓝牙
- • Native 主动通知 JS
2. RN Bridge(旧架构)
传统 RN 架构:
JS Thread
|
| JSON Message
|
Bridge
|
|
Native Modules
Bridge 主要负责:
-
- 方法调用
-
- 参数序列化
-
- 消息传递
例如:
JS:
NativeModules.DeviceInfo.getBattery()
↓
Bridge:
{
"module": "DeviceInfo",
"method": "getBattery"
}
↓
Android:
public class DeviceInfoModule extends ReactContextBaseJavaModule {
@Override
public String getName() {
return "DeviceInfo";
}
@ReactMethod
public void getBattery(Promise promise) {
int level = 80;
promise.resolve(level);
}
}
返回:
80
JS:
const battery =
await NativeModules.DeviceInfo.getBattery();
console.log(battery);
3. Native Module 原生模块桥接
Android
创建 Module:
public class ToastModule
extends ReactContextBaseJavaModule {
@Override
public String getName() {
return "ToastAndroid";
}
@ReactMethod
public void show(String msg) {
Toast.makeText(
getReactApplicationContext(),
msg,
Toast.LENGTH_SHORT
).show();
}
}
JS 调:
import {
NativeModules
} from 'react-native';
NativeModules.ToastAndroid.show(
"Hello Native"
);
iOS
Swift:
@objc(ToastModule)
class ToastModule:
NSObject {
@objc
func show(
_ message:String
){
print(message)
}
}
JS:
NativeModules.ToastModule.show(
"hello ios"
)
4. Native 主动调用 JS
例如:
Native 收到:
- • 推送消息
- • 蓝牙数据
- • 支付结果
需要通知 JS。
流程:
Native
|
EventEmitter
|
Bridge
|
JS Listener
JS:
import {
NativeEventEmitter,
NativeModules
} from 'react-native';
const emitter =
new NativeEventEmitter(
NativeModules.Device
);
emitter.addListener(
"onMessage",
data=>{
console.log(data)
}
);
Native:
Android:
sendEvent(
"onMessage",
params
);
JS 收到:
{
message:"支付成功"
}
5. Native UI 组件桥接
除了调用方法,还可以让 RN 使用原生 View。
例如:
JS:
<MapView
latitude={39.9}
longitude={116.3}
/>
实际:
<MapView>
|
|
Native UIView
|
MKMapView(Android MapView)
Android:
public class MapViewManager
extends SimpleViewManager<MapView>{
@Override
public String getName(){
return "RCTMap";
}
@Override
protected MapView createViewInstance(
ThemedReactContext context
){
return new MapView(context);
}
}
6. TurboModule(新架构)
RN 新架构:
JS
|
JSI
|
C++
|
Native
替代:
JS
|
Bridge(JSON)
|
Native
优势:
| 旧 Bridge | TurboModule |
|---|---|
| JSON 序列化 | 直接调用 |
| 异步为主 | 支持同步 |
| 性能损耗高 | 性能更好 |
| 动态查找 | 静态类型 |
7. Fabric 渲染系统
旧:
JS
|
Bridge
|
UIManager
|
Native View
新:
JS
|
JSI
|
Fabric Renderer
|
Native UI
优势:
- • 更快 UI 更新
- • Concurrent React 支持
- • 更少线程切换
8. JSI 是关键
JSI:
JavaScript Interface
它允许:
JS 直接调用 C++ 对象。
例如:
JS
|
JSI
|
C++
|
C++ Module
|
Native API
很多高性能库:
- • Reanimated 3
- • MMKV
- • Skia
都是基于 JSI。
9. RN 和 Native 通信方式总结
| 场景 | 方案 |
|---|---|
| JS 调 Native 方法 | Native Module |
| Native 通知 JS | EventEmitter |
| 复杂数据流 | JSI |
| 原生 UI | Native Component |
| 高性能计算 | TurboModule + JSI |
| 动画 | Worklet/JSI |
10. 实际开发中怎么选?
普通功能
例如:
- • 获取设备信息
- • 调系统 API
用:
Native Module
高频调用
例如:
- • 视频处理
- • 图像处理
- • 加密
- • 大数据计算
用:
JSI
TurboModule
自定义控件
例如:
- • 地图
- • 视频播放器
- • 图表
用:
Native Component
Fabric
11. 面试常问
Q1:RN Bridge 为什么慢?
因为:
JS对象
↓
JSON序列化
↓
线程切换
↓
Native执行
↓
JSON返回
大量通信会产生开销。
Q2:如何优化 Bridge?
- • 减少 JS-Native 调用次数
- • 批量传数据
- • 使用 JSI
- • 使用 TurboModule
- • Native 处理高频逻辑
Q3:RN 新旧架构区别?
一句话:
老架构靠 Bridge 通信,新架构通过 JSI 让 JS 更直接地访问 Native 能力。