RN启动流程1
就是我们RN页面的容器。ReactActivity里有个ReactRootView,正如它的名字那样,它就是R
eactActivity的root View,最终渲染出来的view都会添加到这个ReactRootView上
。ReactRootView调用自己的startReactApplication()方法启动了整个RN页面,在
启动的过程中先去创建页面上下文ReactContext,然后再去加载、执行并将JavaScript映射成Nat
ive Widget,最终一个RN页面就显示在了用户面前。整个RN页面的启动流程图如下所示:这个流程看起来有点
长,但实际上重要的东西并不多,我们当前只需要重点关注四个问题:ReactInstanceManager是如何被
创建的,它在创建的时候都初始化了哪些对象?RN页面上下文ReactContext在创建的过程中都做了什么,
都初始化了哪些对象?JS Bundle是如何被加载的?JS入口页面是如何被渲染出来的?2.1 创建
ReactInstanceManager我们先来看第一个问题,我们都知道要使用RN页面,就需要先初始化一个Re
actNativeHost,它是一个抽象类,ReactInstanceManager就是在这个类里被创建的,如
下所示:复制代码public abstract class ReactNativeHost { pr
otected ReactInstanceManager createReactInstanceManager
() { ReactInstanceManagerBuilder build
er = ReactInstanceManager.builder() //应用上下文
.setApplication(mApplication) //JSMainM
oduleP相当于应用首页的js Bundle,可以传递url从服务器拉取js Bundle
//当然这个只在dev模式下可以使用 .setJSMainModulePath(getJS
MainModuleName()) //是否开启dev模式 .setUse
DeveloperSupport(getUseDeveloperSupport()) //红
盒的回调 .setRedBoxHandler(getRedBoxHandler())
//JS执行器 .setJavaScriptExecutorFactory(ge
tJavaScriptExecutorFactory()) //自定义UI实现机制,这个我
们一般用不到 .setUIImplementationProvider(getUIImple
mentationProvider()) .setInitialLifecycleState
(LifecycleState.BEFORE_CREATE); //添加我们外面设置的P
ackage for (ReactPackage reactPackage : getPacka
ges()) { builder.addPackage(reactPackage);
} //获取js Bundle的加载路径 String jsBun
dleFile = getJSBundleFile(); if (jsBundleFile !=
null) { builder.setJSBundleFile(jsBundleFile)
; } else { builder.setBundleAssetName(A
ssertions.assertNotNull(getBundleAssetName()));
} return builder.build(); }}2.2 创建ReactCont
ext我们再来看第二个问题,ReactContext创建流程序列图如下所示:可以发现,最终创建ReactCon
text是createReactContext()方法,我们来看看它的实现。复制代码public class
ReactInstanceManager { private ReactApplicationC
ontext createReactContext( JavaScriptExecutor j
sExecutor, JSBundleLoader jsBundleLoader) {
Log.d(ReactConstants.TAG, "ReactInstanceManager.crea
teReactContext()"); ReactMarker.logMarker(CREATE_
REACT_CONTEXT_START); //ReactApplicationContext是R
eactContext的包装类。 final ReactApplicationContext re
actContext = new ReactApplicationContext(mApplicationCo
ntext); //debug模式里开启异常处理器,就是我们开发中见到的调试工具(红色错误框
等) if (mUseDeveloperSupport) { reactConte
xt.setNativeModuleCallExceptionHandler(mDevSupportManag
er); } //创建JavaModule注册表 NativeMod
uleRegistry nativeModuleRegistry = processPackages(reac
tContext, mPackages, false); NativeModuleCallE
xceptionHandler exceptionHandler = mNativeModuleCallExc
eptionHandler != null ? mNativeModuleCallExcept
ionHandler : mDevSupportManager; /
/创建CatalystInstanceImpl的Builder,它是三端通信的管理类 Cataly
stInstanceImpl.Builder catalystInstanceBuilder = new Ca
talystInstanceImpl.Builder() .setReactQueueConf
igurationSpec(ReactQueueConfigurationSpec.createDefault
()) //JS执行器 .setJSExecutor(jsExecutor)
//Java Module注册表 .setRegistry(nativeMod
uleRegistry) //JS Bundle加载器 .setJSBundl
eLoader(jsBundleLoader) //Java Exception处理器
.setNativeModuleCallExceptionHandler(exceptionHand
ler); ReactMarker.logMarker(CREATE_CATALYST_IN
STANCE_START); // CREATE_CATALYST_INSTANCE_END is
in JSCExecutor.cpp Systrace.beginSection(TRACE_T
AG_REACT_JAVA_BRIDGE, "createCatalystInstance");
final CatalystInstance catalystInstance; //构建Cata
lystInstance实例 try { catalystInstance = c
atalystInstanceBuilder.build(); } finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_EN
D); } if (mBridgeIdleDebugListener != nu
ll) { catalystInstance.addBridgeIdleDebugListen
er(mBridgeIdleDebugListener); } if (Systrac
e.isTracing(TRACE_TAG_REACT_APPS | TRACE_TAG_REACT_JS_V
M_CALLS)) { catalystInstance.setGlobalVariable(
"__RCTProfileIsProfiling", "true"); } React
Marker.logMarker(ReactMarkerConstants.PRE_RUN_JS_BUNDLE
_START); //开启加载执行JS Bundle catalystInstance
.runJSBundle(); //关联catalystInstance与reactContext
reactContext.initializeWithInstance(catalystInst
ance); return reactContext; } }在这个方法里完成了RN
页面上下文ReactContext的创建,我们先来看看这个方法的两个入参:JSCJavaScriptExecu
tor jsExecutor:JSCJavaScriptExecutor继承于JavaScriptExecut
or,当该类被加载时,它会自动去加载"reactnativejnifb.so"库,并会调用Native方法in
itHybrid()初始化C++层RN与JSC通信的框架。JSBundleLoader jsBundleLoa
der:缓存了JSBundle的信息,封装了上层加载JSBundle的相关接口,CatalystInstanc
e通过其简介调用ReactBridge去加载JS文件,不同的场景会创建不同的加载器,具体可以查看类JSBund
leLoader。可以看到在ReactContext创建的过程中,主要做了以下几件事情:构建ReactAppl
icationContext对象,ReactApplicationContext是ReactContext的包
装类。利用jsExecutor、nativeModuleRegistry、jsBundleLoader、exc
eptionHandler等参数构建CatalystInstance实例,作为以为三端通信的中枢。调用Cata
lystInstance的runJSBundle()开始加载执行JS。另一个重要的角色CatalystInst
ance出现了,前面我们也说过它是三端通信的中枢。关于通信的具体实现我们会在接下来的通信机制小节来讲述,我们先
来接着看JS的加载过程。