- 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是如何被创建的,它在创建的时候都初始化了哪些对象?🤔
- RN页面上下文ReactContext在创建的过程中都做了什么,都初始化了哪些对象?🤔
- JS Bundle是如何被加载的?🤔
- JS入口页面是如何被渲染出来的?🤔
2.1 创建ReactInstanceManager
我们先来看第一个问题,我们都知道要使用RN页面,就需要先初始化一个ReactNativeHost,它是一个抽象类,ReactInstanceManager就是在这个类里被创建的,如下所示:
public abstract class ReactNativeHost {
protected ReactInstanceManager createReactInstanceManager() {
ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
//应用上下文
.setApplication(mApplication)
//JSMainModuleP相当于应用首页的js Bundle,可以传递url从服务器拉取js Bundle
//当然这个只在dev模式下可以使用
.setJSMainModulePath(getJSMainModuleName())
//是否开启dev模式
.setUseDeveloperSupport(getUseDeveloperSupport())
//红盒的回调
.setRedBoxHandler(getRedBoxHandler())
//JS执行器
.setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
//自定义UI实现机制,这个我们一般用不到
.setUIImplementationProvider(getUIImplementationProvider())
.setInitialLifecycleState(LifecycleState.BEFORE_CREATE);
//添加我们外面设置的Package
for (ReactPackage reactPackage : getPackages()) {
builder.addPackage(reactPackage);
}
//获取js Bundle的加载路径
String jsBundleFile = getJSBundleFile();
if (jsBundleFile != null) {
builder.setJSBundleFile(jsBundleFile);
} else {
builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName()));
}
return builder.build();
}
}
2.2 创建ReactContext
我们再来看第二个问题,ReactContext创建流程序列图如下所示:
可以发现,最终创建ReactContext是createReactContext()方法,我们来看看它的实现。
public class ReactInstanceManager {
private ReactApplicationContext createReactContext(
JavaScriptExecutor jsExecutor,
JSBundleLoader jsBundleLoader) {
Log.d(ReactConstants.TAG, “ReactInstanceManager.createReactContext()”);
ReactMarker.logMarker(CREATE_REACT_CONTEXT_START);
//ReactApplicationContext是ReactContext的包装类。
final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);
//debug模式里开启异常处理器,就是我们开发中见到的调试工具(红色错误框等)
if (mUseDeveloperSupport) {
reactContext.setNativeModuleCallExceptionHandler(mDevSupportManager);
}
//创建JavaModule注册表
NativeModuleRegistry nativeModuleRegistry = processPackages(reactContext, mPackages, false);
NativeModuleCallExceptio