RN 0.63 双端冷启动线程流转

RN 0.63 旧架构下,Android 和 iOS 的冷启动都经历了相同的思路:主线程入口 → 后台线程做重活(创建引擎、加载 Bundle)→ JS Thread 接管 → Shadow 计算布局 → 主线程渲染首帧。两端实现细节不同,但线程模型一致。


一、涉及的线程

iOS(4 条线程/队列)

线程/队列 名称 负责什么
主线程 Main Thread AppDelegate 入口、RCTRootView 挂载、最终 UIKit 渲染
后台初始化队列 Init(GCD background queue) 创建 JS 引擎、JS Thread、注册模块、加载 Bundle
JS 线程 JS Thread(NSThread + CFRunLoop) 执行 Bundle,驱动后续 JS 逻辑
布局计算队列 Shadow Queue(GCD serial queue) Yoga 布局计算,生成 UIBlocks

Android(5 条线程)

线程 名称 负责什么
主线程 Main Thread App 入口、Activity 创建、ReactContext 挂载、最终 UI 渲染
后台初始化线程 Init Thread(AsyncTask) 创建 JS 引擎、Bridge、注册模块、加载 Bundle
JS 线程 JS Thread(MessageQueueThread) Bundle 执行完后启动,负责所有后续 JS 逻辑
布局计算线程 Shadow Thread Yoga 计算布局,构建 Shadow Tree
UI 线程 UI Thread 将布局结果转成真实 Android View(实际就是主线程)

二、iOS 冷启动流转

复制代码
┌──────────────────────────────────────────────────────────┐
│                   1. App 冷启动(主线程)                  │
└──────────────────────────────────────────────────────────┘
      │
      ▼
┌───────────────────────────────────────────────┐
│ AppDelegate.application:didFinishLaunching     │
│ 创建 RCTBridge(只是配置,未启动 JS)            │
│ 创建 RCTRootView                               │
└───────────────────────────────────────────────┘
      │
      ▼
┌───────────────────────────────────────────────┐
│ RCTRootView 触发 RCTBridge 开始初始化           │
│ → RCTBridge 内部创建 RCTCxxBridge              │
└───────────────────────────────────────────────┘
      │
      ▼
══════════════════ ✦ 切入后台队列(GCD background) ✦ ══════════════════

┌──────────────────────────────────────────────────────────┐
│     2. RCTCxxBridge 初始化(后台 GCD queue)               │
└──────────────────────────────────────────────────────────┘
      │
      ▼
┌─────────────────────────────────────────────┐
│ a. 创建 JS 引擎(JSC 或 Hermes)              │
└─────────────────────────────────────────────┘
      │
      ▼
┌─────────────────────────────────────────────┐
│ b. 创建 JS Thread                            │
│    NSThread + CFRunLoop 驱动                 │
│    线程名:com.facebook.react.JavaScript      │
└─────────────────────────────────────────────┘
      │
      ▼
┌─────────────────────────────────────────────┐
│ c. 注册 NativeModules                        │
│    扫描所有 RCTBridgeModule,生成模块配置表    │
└─────────────────────────────────────────────┘
      │
      ▼
┌─────────────────────────────────────────────┐
│ d. 加载 JS Bundle                            │
│    Dev:HTTP 读取 Metro                      │
│    Release:NSBundle mainBundle              │
└─────────────────────────────────────────────┘

══════════════════ ✦ 切到 JS Thread ✦ ══════════════════

      ▼
┌──────────────────────────────────────────────────────────┐
│     3. 执行 JS Bundle(JS Thread)                        │
│        - 定义所有模块                                      │
│        - 注册 ViewManagers                                │
│        - AppRegistry.registerComponent                    │
└──────────────────────────────────────────────────────────┘
      │
      ▼
══════════════════ ✦ 切回主线程 ✦ ══════════════════

┌──────────────────────────────────────────────────────────┐
│     4. RCTBridge 通知 RCTRootView bridge 就绪(主线程)    │
│        → 调用 AppRegistry.runApplication                  │
│        → JS 开始描述 UI 结构                               │
└──────────────────────────────────────────────────────────┘
      │
      ▼
══════════════════ ✦ 切到 Shadow Queue ✦ ══════════════════

┌─────────────────────────────────────────────┐
│ 5. RCTShadowView 布局计算(Shadow Queue)     │
│    - 构建 Shadow Tree                        │
│    - Yoga 计算布局                           │
│    - 生成 UIBlocks 放入 _pendingUIBlocks      │
└─────────────────────────────────────────────┘
      │
      ▼
══════════════════ ✦ 切回主线程 ✦ ══════════════════

┌─────────────────────────────────────────────┐
│ 6. RCTUIManager flush UIBlocks(主线程)      │
│    - 创建 / 更新真实 UIKit View               │
│    - 由 CADisplayLink 每帧触发               │
└─────────────────────────────────────────────┘
      │
      ▼
┌─────────────────────────────────────────────┐
│ 7. RN UI 首帧渲染完成                         │
└─────────────────────────────────────────────┘

三、Android 冷启动流转

复制代码
┌──────────────────────────────────────────────────────────┐
│                   1. App 冷启动(主线程)                  │
└──────────────────────────────────────────────────────────┘
      │
      ▼
┌───────────────────────────────────────────────┐
│ Application.onCreate()                         │
│ 创建 ReactNativeHost(仅配置,不创建 RN 实例)  │
└───────────────────────────────────────────────┘
      │
      ▼
┌───────────────────────────────────────────────┐
│ Activity.onCreate()                            │
│ 创建 ReactRootView                             │
└───────────────────────────────────────────────┘
      │
      ▼
┌───────────────────────────────────────────────┐
│ ReactRootView.startReactApplication()          │
│ → 获取 ReactInstanceManager(RIM)             │
│ → RIM.createReactContextInBackground()         │
└───────────────────────────────────────────────┘
      │
      ▼
══════════════════ ✦ 切入后台线程(Init Thread) ✦ ══════════════════

┌──────────────────────────────────────────────────────────┐
│     2. ReactContextInitAsyncTask.run()(后台线程)         │
└──────────────────────────────────────────────────────────┘
      │
      ▼
┌─────────────────────────────────────────────┐
│ a. 创建 JS 引擎(JSC 或 Hermes)              │
└─────────────────────────────────────────────┘
      │
      ▼
┌─────────────────────────────────────────────┐
│ b. 创建 CatalystInstance(C++ Bridge)        │
│    JS ↔ C++ ↔ JNI ↔ Java 四层通信            │
└─────────────────────────────────────────────┘
      │
      ▼
┌─────────────────────────────────────────────┐
│ c. 注册 NativeModules(由 ReactPackage 提供) │
└─────────────────────────────────────────────┘
      │
      ▼
┌─────────────────────────────────────────────┐
│ d. 加载 JS Bundle                            │
│    Dev:HTTP 读取 Metro                      │
│    Release:assets://main.jsbundle           │
└─────────────────────────────────────────────┘
      │
      ▼
┌──────────────────────────────────────────────────────────┐
│ e. 执行 JS Bundle                                         │
│    - 定义所有模块                                          │
│    - 注册 UIManager / ViewManagers                        │
│    - AppRegistry.registerComponent                        │
│    → JS Thread 启动(MessageQueueThread)                 │
└──────────────────────────────────────────────────────────┘

══════════════════ ✦ 切回主线程 ✦ ══════════════════

      ▼
┌──────────────────────────────────────────────────────────┐
│ 3. RIM.setupReactContext()(主线程)                       │
│    - 创建 ReactContext                                     │
│    - 通知所有 ReactRootView attach                         │
│    - 触发 UIManager.createRoot                            │
└──────────────────────────────────────────────────────────┘
      │
      ▼
══════════════════ ✦ 切到 Shadow Thread ✦ ══════════════════

┌─────────────────────────────────────────────┐
│ 4. Yoga 布局计算(Shadow Thread)             │
│    - 构建 Shadow Tree                        │
│    - 计算各节点尺寸和位置                     │
└─────────────────────────────────────────────┘
      │
      ▼
══════════════════ ✦ 切到 UI Thread(主线程) ✦ ══════════════════

┌─────────────────────────────────────────────┐
│ 5. UIManager 操作 Android View               │
│    createView / updateView / manageChildren  │
└─────────────────────────────────────────────┘
      │
      ▼
┌─────────────────────────────────────────────┐
│ 6. RN UI 首帧渲染完成                         │
└─────────────────────────────────────────────┘

四、双端对比

环节 Android iOS
应用入口 Application.onCreate() + Activity.onCreate() AppDelegate.application:didFinishLaunching
RN 根视图 ReactRootView RCTRootView
Bridge 管理器 ReactInstanceManager(RIM) RCTBridge
Bridge 实体 CatalystInstance(Java + JNI + C++) RCTCxxBridge(ObjC + C++,无 JNI)
后台初始化方式 AsyncTask 后台 GCD queue
JS Thread 驱动 MessageQueueThread(Looper/Handler) NSThread + CFRunLoop
NativeModule 注册 ReactPackage RCTBridgeModule
Shadow 计算 Shadow Thread(独立 Java 线程) Shadow Queue(GCD serial queue)
UI 更新 UIManager → Android View RCTUIManager → UIKit View
UI 帧驱动 Choreographer CADisplayLink
通信层 JS ↔ C++ ↔ JNI ↔ Java(4层) JS ↔ C++ ↔ ObjC(3层,无 JNI)

iOS 比 Android 少一层 JNI,因为 ObjC 支持直接混编 C++(.mm 文件),不需要额外的跨语言桥接。


五、名词解释

ReactNativeHost

Android 侧 RN 的全局配置容器,工厂模式。只持有配置(Bundle 路径、Dev 模式开关等),不直接创建 RN 实例,由 ReactInstanceManager 负责真正的初始化。

ReactRootView / RCTRootView

RN 的根视图容器。Android 侧继承自 FrameLayout,iOS 侧继承自 UIView。作用一样:作为 Native 布局和 RN 渲染内容的边界,RN 渲染的所有组件都挂在它下面。

ReactInstanceManager(RIM)

Android 侧 RN 实例的调度中心。负责创建 JS 引擎、管理 ReactContext 生命周期、协调各线程的初始化顺序。iOS 侧对应的是 RCTBridge

ReactContextInitAsyncTask

Android 的 AsyncTask 子类,专门把 RN 初始化的耗时工作(创建引擎、加载 Bundle)移到后台线程,避免主线程被阻塞。

CatalystInstance

旧架构 Android 侧的 Bridge 核心实体,负责 JS ↔ C++ ↔ JNI ↔ Java 四层通信。所有 JS 调 Native、Native 调 JS 都经过它,且必须 JSON 序列化。新架构用 JSI 替掉了它。

JNI(Java Native Interface)

Java 调用 C/C++ 原生代码的桥接机制。因为 JS 引擎(JSC/Hermes)是 C++ 写的,Android 业务层是 Java,两者必须通过 JNI 跨语言调用。iOS 没有这层,ObjC 可以直接混编 C++。

ReactPackage

Android 侧注册 NativeModule 的方式。开发者实现 ReactPackage 接口并返回模块列表,RN 初始化时统一扫描注册。iOS 侧用 RCTBridgeModule 宏替代,自动注册,不需要手动列举。

JS Bundle

Metro 打包后的 JavaScript 产物(main.jsbundle)。包含所有业务代码和第三方库。Dev 模式从 Metro HTTP 服务实时拉取,Release 模式预先打包进 App 资源目录。

MessageQueueThread

Android 侧 JS Thread 的实现,基于 Looper + Handler 机制。是一个有消息队列的后台线程,所有 JS 任务串行投递到这里执行。iOS 侧对应的是 NSThread + CFRunLoop

ReactContext

RN 的运行时容器,持有 JS 执行环境、NativeModule 注册表、Bridge 实例等。可以理解为 RN 的"全局上下文",初始化完成后通知所有 ReactRootView 开始渲染。

UIManager / RCTUIManager

负责将 JS 描述的 UI 结构转换为真实 Native View 的管理器。接收来自 JS 的 createViewupdateViewmanageChildren 等指令,在主线程操作真实 View。

Shadow Tree / ShadowNode / RCTShadowView

RN 的虚拟布局树。每个 JS 组件对应一个 Shadow 节点,存储布局属性(宽高、padding、flex 等)。布局计算在 Shadow Thread / Shadow Queue 中进行,不占用主线程。

Yoga

Facebook 开源的跨平台布局引擎,实现了 CSS Flexbox 规范,Android 和 iOS 共用同一套 C++ 实现。RN 在 Shadow Thread 中用 Yoga 计算每个节点的实际尺寸和位置。

RCTBridge / RCTCxxBridge

iOS 侧的 Bridge 管理器(RCTBridge)及其 C++ 实现层(RCTCxxBridge)。RCTBridge 是对外的 ObjC 接口,RCTCxxBridge 是真正执行初始化的 C++ 核心,负责创建 JS 引擎、JS 线程、注册模块。

RCTBridgeModule

iOS NativeModule 的注册协议。在 ObjC 类里加上 RCT_EXPORT_MODULE() 宏,RN 初始化时自动扫描注册,不需要像 Android 那样在 ReactPackage 里手动列举。

_pendingUIBlocks
RCTUIManager 内部的待执行 UI 操作队列。Shadow Queue 计算完布局后,把需要做的 View 操作封装成 Block 放进来,等 CADisplayLink 触发时批量提交到主线程执行,避免频繁切换主线程。

CADisplayLink / Choreographer

屏幕刷新率同步计时器。iOS 用 CADisplayLink,Android 用 Choreographer,都是每帧(~16.7ms)触发一次,驱动 RN 把 _pendingUIBlocks 批量提交到主线程更新 UI。


六、与新架构的对比

旧架构(0.63)的瓶颈主要集中在 Init Thread 这一段:

旧架构 新架构改进
CatalystInstance:四层序列化通信 JSI:JS 直接持有 C++ 对象引用,无序列化
NativeModules 启动时全量注册 TurboModules:懒加载,首次调用时才初始化
Shadow Tree 可变,需要线程锁 Fabric:Shadow Tree 不可变,多线程安全
不支持 React 并发特性 Fabric 支持可中断渲染、优先级调度
相关推荐
CC_Amber3 小时前
Flexbox 在 RN 中的行为差异 & css注意
react native
CC_Amber5 小时前
浅谈 RN新架构与老架构
react native
弓.长.5 小时前
ReactNative for OpenHarmony项目鸿蒙化三方库:react-native-flash-message — 闪现消息组件
react native·react.js·harmonyos
弓.长.5 小时前
ReactNative for OpenHarmony项目鸿蒙化三方库:react-native-snap-carousel — 轮播组件
react native·react.js·harmonyos
弓.长.5 小时前
ReactNative for OpenHarmony项目鸿蒙化三方库:react-native-animatable — 动画组件
react native·react.js·harmonyos
CC_Amber6 小时前
RN线程模型
react native
弓.长.6 小时前
ReactNative for OpenHarmony项目鸿蒙化三方库:react-native-shimmer-placeholder — 骨架屏组件
react native·react.js·harmonyos
早點睡3902 天前
ReactNative项目OpenHarmony三方库集成实战:react-native-calendar-events(读取不到日历里新增的事件,待排查)
javascript·react native·react.js
早點睡3903 天前
ReactNative项目OpenHarmony三方库集成实战:react-native-render-html
react native·react.js·html