在 React Native(RN) 里,JS 和原生(Android / iOS)之间的通信 是一个核心机制。下面我按你关心的点,从线程模型 → 通信原理 → 通信方式 → 新旧架构对比,系统地讲一遍(偏工程视角)。
一、RN 是单线程还是多线程?
结论一句话
RN 是多线程架构,但 JS 执行本身是单线程的
RN 中的核心线程(经典架构)
1️⃣ JS Thread(单线程)
-
执行 JS 代码(业务逻辑、状态更新)
-
JS 是 单线程运行
-
如果 JS 线程阻塞:
-
UI 不更新
-
动画卡顿
-
手势延迟
-
2️⃣ UI Thread(主线程)
-
原生 UI 渲染
-
处理触摸事件
-
不能阻塞
3️⃣ Native Modules Thread(或 Background Thread)
-
执行原生模块逻辑
-
IO / 网络 / 计算
-
可多线程并行
┌─────────────┐
│ JS Thread │ (单线程)
└─────────────┘
│
Bridge
│
┌─────────────┐ ┌──────────────────┐
│ UI Thread │ │ Native Modules │ (多线程)
└─────────────┘ └──────────────────┘
二、RN 和原生通信的本质
核心思想
JS 与 Native 不能直接互相调用函数,只能通过"通信机制"
原因:
-
JS 运行在 JS 引擎(Hermes / JSC)
-
Native 运行在 JVM / Objective-C Runtime
-
运行时不同,内存不共享(旧架构)
三、RN 与原生通信方式(重点)
1️⃣ Bridge 通信(经典 / 旧架构)
这是你必须掌握的基础。
通信特点
-
异步
-
序列化(JSON)
-
跨线程
-
有性能瓶颈
通信流程(JS → Native)
JS 调用
↓
参数序列化成 JSON
↓
Bridge 队列
↓
Native Module 方法
JS → Native
import { NativeModules } from 'react-native';
NativeModules.DeviceModule.getDeviceInfo()
Native → JS(Callback / Promise)
@ReactMethod
public void getDeviceInfo(Promise promise) {
promise.resolve("Android");
}
适合场景
-
普通业务
-
调系统能力
-
网络、文件、设备信息
缺点
-
大量调用 → 卡顿
-
高频通信(动画、手势)不合适
2️⃣ Callback / Promise(Bridge 的具体形式)
Callback
NativeModules.TestModule.doSomething((res) => {});
-
老方式
-
回调地狱
-
不推荐新项目使用
Promise(推荐)
await NativeModules.TestModule.doSomething();
3️⃣ EventEmitter(Native → JS 事件)
适合 状态变化通知
JS 监听
const emitter = new NativeEventEmitter(NativeModules.TestModule);
emitter.addListener('onChange', (data) => {
console.log(data);
});
Native 发送
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("onChange", data);
场景
-
传感器
-
网络状态
-
原生回调事件
4️⃣ UI Component 通信(Props + Commands)
JS → Native UI
-
通过 props
<CustomView color="red" />
Native → JS
-
通过事件回调
<CustomView onChange={handleChange} />
特点
-
UI 级别通信
-
性能优于普通 NativeModule
四、新架构通信方式(Fabric / TurboModules / JSI)
这是 RN 0.68+ / 0.71+ 的重点
5️⃣ JSI(JavaScript Interface)🔥
最大变化
JS 可以直接调用 C++ / Native 方法,无需 Bridge
特点
-
同步调用
-
无 JSON 序列化
-
共享内存
-
性能极高
调用示意
JS ↔ C++ ↔ Native
使用场景
-
高性能计算
-
动画
-
手势
-
音视频
-
游戏
6️⃣ TurboModules(JSI + Native Modules)
-
新一代 NativeModule
-
类型安全
-
同步 / 异步
-
无 Bridge 队列
const device = TurboModuleRegistry.get('DeviceModule');
device.getInfo(); // 同步 or 异步
7️⃣ Fabric(新 UI 架构)
-
UI 渲染走 C++
-
减少 JS ↔ UI 通信
-
与 JSI 深度结合
五、通信方式对比总结(非常重要)
| 通信方式 | 是否同步 | 性能 | 适用场景 |
|---|---|---|---|
| Bridge | ❌ 异步 | 一般 | 普通业务 |
| Callback | ❌ | 一般 | 老代码 |
| Promise | ❌ | 一般 | 推荐 |
| EventEmitter | ❌ | 一般 | 事件通知 |
| UI Props/Event | 半同步 | 较好 | UI 通信 |
| JSI | ✅ | ⭐⭐⭐⭐ | 高频 / 高性能 |
| TurboModule | ✅ / ❌ | ⭐⭐⭐⭐ | 新架构 |
六、面试 & 实战常考点(给你划重点)
面试常问
-
RN 为什么 JS 是单线程?
-
Bridge 为什么慢?
-
如何避免 JS 卡顿?
-
JSI 为什么快?
-
TurboModules 和 NativeModules 区别?
实战建议
-
普通功能 → NativeModules
-
高频调用 → JSI
-
UI 通信 → Fabric / UIManager
-
事件通知 → EventEmitter