1. 为什么需要了解架构?
作为一名 Android 工程师,你深知 UI 线程(Main Thread)被阻塞会导致掉帧(ANR 或卡顿)。在 React Native 中,JavaScript 代码和原生的 Android/iOS 代码是运行在不同线程的,它们之间的通信机制直接决定了应用的性能。
2. 旧架构:Bridge 时代
在很长一段时间里,RN 依赖一个名为 Bridge 的机制进行通信。
它是如何工作的?
- JS 线程计算出 UI 的变更(比如要渲染一个按钮)。
- 这些变更会被序列化成 JSON 字符串。
- JSON 字符串通过 Bridge 发送到原生(Android)线程。
- 原生线程解析 JSON,然后调用 Android 原生的
Button控件进行渲染。
痛点(为什么被吐槽慢?)
- 异步通信:JS 和 Native 的通信是异步的。如果 JS 想获取原生视图的尺寸,它必须发送请求,等待下一帧原生返回结果,这就导致了诸如手势动画延迟、列表滑动白屏等问题。
- 序列化开销:大量数据的 JSON 序列化和反序列化非常耗时,尤其是在老旧的 Android 手机上。
类比 Android:这就像是在两个不同的进程之间,只能通过把对象转成 JSON 字符串,然后用 Intent 传过去一样,效率极低。
3. 破局者:JSI (JavaScript Interface)
为了解决 Bridge 的问题,RN 引入了 JSI(基于 C++)。
核心改变
JSI 允许 JS 引擎(如 Hermes)直接持有 C++ 对象的引用,并直接调用其方法,无需序列化为 JSON。由于 Android (JNI) 也能与 C++ 互通,这意味着 JS 可以几乎同步地调用 Android 原生方法!
类比 Android:这就好比你使用 JNI 直接在 Java 中调用 C++ 函数,虽然有微小的 JNI 开销,但没有序列化负担,而且是同步的。
4. 新架构双子星:Fabric 与 TurboModules
有了 JSI 这个底层基石,RN 团队重写了 UI 渲染和原生模块层。
Fabric (新 UI 架构)
- 直接调用:JS 可以直接通过 JSI 创建和更新原生 UI 节点。
- 同步渲染:JS 现在可以同步测量原生视图的尺寸。当你滚动列表时,UI 和 JS 逻辑可以保持在同一帧内,彻底消除了异步带来的卡顿。
- 类比 Compose:Fabric 让 RN 的 UI 树更新过程更像 Compose,由状态驱动,并高效、同步地计算 Diff。
TurboModules (新原生模块)
在旧架构中,所有的原生模块(如蓝牙、相册)在应用启动时就会全部初始化,拖慢启动速度。
- 懒加载:通过 JSI,JS 只有在第一次调用该模块时,TurboModules 才会去初始化对应的 Android 原生模块。
- 强类型:通过 Codegen 工具,可以在编译期保证 JS 调用原生方法时的类型安全(不会出现 JS 传了 String,Android 期望 Int 导致的 Crash)。
5. 总结
RN 已经摆脱了“Bridge 通信慢”的历史包袱。基于 JSI 的新架构(Fabric/TurboModules)在底层通过 C++ 打通了 JS 和 Native 的壁垒,使得 RN 在动画处理、手势响应等重度交互场景下的性能已经非常接近原生 Android 和 Compose。作为原生开发者,现在拥抱 RN 正是最好的时机。