在 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