郭孝星,程序员,吉他手,主要从事 Android 平台基础架构方面的工作,欢迎交流技术方面的问题,可以去我的 Github 提 issue 或者发邮件至 guoxiaoxingse@163.com 与我交流.
文章目录
一 原理概览
二 启动流程
2.1 创建 ReactInstanceManager
2.2 创建 ReactContext
2.3 加载 JS Bundle
2.4 绑定 ReactContext 与 ReactRootView
三 渲染原理
3.1 JavaScript 层组件渲染
3.2 Java 层组件渲染
四 通信机制
4.1 创建注册表
4.2 创建通信桥
从 2016 年中开始,我司开始筹措推进 React Native 在全公司的推广使用,从最基础的基础框架搭建开始,到各种组件库,开发工具的完善,经历了诸多波折,也累积了很多经验.今年的工作也 马上接近尾声,打算写几篇文章来对这一年多的实践经验做个总结.读者有什么问题或者想要交流的地方,可以去 vinci 提 issue.
预先善其事,必先利其器.开篇第一篇文章我们还是从 React Native 实现原理讲起,事实上原理分析的文章之前就有写过,但是鉴于最新的版本 0.52.0 源码有 不少的改动,我们就再重新温习一下,这样过渡到后续的内容,才更加容易理解.
一 原理概览
源码地址:https://github.com/facebook/react-native
源码版本:
当你拿到 React Native 的源码的时候,它的目录结构是这样的:
jni:ReactNative 的好多机制都是由 C,C++ 实现的,这部分便是用来载入 SO 库.
perftest:测试配置
proguard:混淆
quicklog:log 输出
react:ReactNative 源码的主要内容,也是我们分析的主要内容.
systrace:system trace
yoga:瑜伽?哈哈,并不是,是 facebook 开源的前端布局引擎
总体来看,整套 React Native 框架分为三层,如下图所示:
Java 层:该层主要提供了 Android 的 UI 渲染器 UIManager(将 JavaScript 映射成 Android Widget)以及一些其他的功能组件(例如:Fresco,Okhttp)等.
C++ 层:该层主要完成了 Java 与 JavaScript 的通信以及执行 JavaScript 代码两件工作.
JavaScript 层:该层提供了各种供开发者使用的组件以及一些工具库.
注:JSCore,即 JavaScriptCore,JS 解析的核心部分,IOS 使用的是内置的 JavaScriptCore,Androis 上使用的是 https://webkit.org 家的 jsc.so.
通过上面的分析,我们理解了 React Native 的框架结构,除此之外,我们还要理解整套框架里的一些重要角色,如下所示:
ReactContext:ReactContext 继承于 ContextWrapper,是 ReactNative 应用的上下文,通过 getContext() 去获得,通过它可以访问 ReactNative 核心类的实现.
ReactInstanceManager:ReactInstanceManager 是 ReactNative 应用总的管理类,创建 ReactContext,CatalystInstance 等类,解析 ReactPackage 生成映射表,并且配合 ReactRootView 管理 View 的创建与生命周期等功能.
CatalystInstance:CatalystInstance 是 ReactNative 应用 Java 层,C++ 层,JS 层通信总管理类,总管 Java 层,JS 层核心 Module 映射表与回调,三端通信的入口与桥梁.
NativeToJsBridge:NativeToJsBridge 是 Java 调用 JS 的桥梁,用来调用 JS Module,回调 Java.
JsToNativeBridge:JsToNativeBridge 是 JS 调用 Java 的桥梁,用来调用 Java Module.
JavaScriptModule:JavaScriptModule 是 JS Module,负责 JS 到 Java 的映射调用格式声明,由 CatalystInstance 统一管理.
NativeModule:NativeModule 是 ava Module,负责 Java 到 Js 的映射调用格式声明,由 CatalystInstance 统一管理.
JavascriptModuleRegistry:JavascriptModuleRegistry 是 JS Module 映射表,NativeModuleRegistry 是 Java Module 映射表
以上便是整套框架中关键的角色,值得一提的是,当页面真正渲染出来以后,它实际上还是 Native 代码,React Native 的作用就是把 JavaScript 代码映射成 Native 代码以及实现两端 的通信,所以我们在 React Native 基础框架搭建的过程中,指导思路之一就是弱化 Native 与 RN 的边界与区别,让业务开发组感受不到两者的区别,从而简化开发流程.
好,有了对 React Native 框架的整体理解,我们来继续分析一个 RN 页面是如何启动并渲染出来的,这也是我们关心的主要问题.后续的基础框架的搭建,JS Bundle 分包加载,渲染性能优化 等都会围绕着着一块做文章.
二 启动流程
我们知道 RN 的页面也是依托 Activity,React Native 框架里有一个 ReactActivity,它就是我们 RN 页面的容器.ReactActivity 里有个 ReactRootView,正如它的名字那样,它就是 ReactActivity 的 root View,最终渲染出来的 view 都会添加到这个 ReactRootView 上.ReactRootView 调用自己的 startReactApplication() 方法启动了整个 RN 页面,在启动的过程 中先去创建页面上下文 ReactContext,然后再去加载,执行并将 JavaScript 映射成 Native Widget,最终一个 RN 页面就显示在了用户面前.
整个 RN 页面的启动流程图如下所示:
这个流程看起来有点长,但实际上重要的东西并不多,我们当前只需要重点关注四个问题:
ReactInstanceManager 是如何被创建的,它在创建的时候都初始化了哪些对象?
来源: https://juejin.im/post/5a6460f8f265da3e4f0a446d