ReactNative 详解(四) 源码之RN启动过程

本章主要来探讨一下,RN 的启动过程都做了什么?同时简单的介绍下在 Android 中是如何实现 ReactNative 的。进而引出解决一个重要的问题,ReactNative 的预加载。

ReactNative 系统框架概述

ReactNative 源码结构图如下:

a.png

其中几个主要内容:

  • Libraries:JS层的实现,实现了JS组件的封装与JS队列的封装
  • ReactAndroid:Android 源码实现
  • ReactCommon:C++ 层实现,实现了对脚本引擎JSC的封装与通信桥ReactBridge,Android与iOS调用
  • React:ReactNative源码的主要内容

ReactNative 主要工作就两部分:
第一部分实现:ReactNative 应用启动流程;ReactNative应用UI的绘制与渲染;ReactNative应用通信机制;ReactNative应用线程模型
第二部分:ReactNative运行时的异常以及异常的捕获与处理;SOLoader加载动态链接库;ReactNative触摸事件处理机制。

我们先从一个 Demo 工程来看 ReactNative 启动流程

启动流程

应用初始化

首先,我们打开这个普通工程的 android 目录,这里就是一个完整的 android 项目。

  1. 首先我们看 MainApplication.java 里面的 RN 的初始化操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage()
);
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
// SoLoader 加载
SoLoader.init(this, /* native exopackage */ false);
}
}

ReactApplication 可以看到我们在Application里实现了 ReactApplication接口,该接口要求创建一个ReactNativeHost对象。ReactNativeHost 对象,本身持有 ReactInstanceManager 对象。其对外暴露两个需要实现的方法:

1
2
3
4
5
6
7
//是否开启dev模式,dev模式下会有一些调试工具
public abstract boolean getUseDeveloperSupport();
// 返回app需要的ReactPackage,这些ReactPackage里包含了运行时需要用到的NativeModule
// JavaScriptModule以及ViewManager
// 我们的自定义 Module 也是在这里添加的
protected abstract List<ReactPackage> getPackages();

ReactNativeHost主要的工作就是创建 ReactInstanceManager,创建部分代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public abstract class ReactNativeHost {
protected ReactInstanceManager createReactInstanceManager() {
// Builder 模式,创建 ReactInstanceManager 实例
ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
// 设置应用上下文
.setApplication(mApplication)
// 设置应用的 jsBundle,可以传给 url 来使其从服务器拉去 jsBundle
// 仅在 dev 下生效
.setJSMainModulePath(getJSMainModuleName())
// 是否开启 dev 模式
.setUseDeveloperSupport(getUseDeveloperSupport())
// 红盒回调
.setRedBoxHandler(getRedBoxHandler())
.setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
// 自定义UI实现机制,不会使用
.setUIImplementationProvider(getUIImplementationProvider())
.setJSIModulesPackage(getJSIModulePackage())
.setInitialLifecycleState(LifecycleState.BEFORE_CREATE);
// 添加ReactPackage (就是我们复写的抽象方法)
for (ReactPackage reactPackage : getPackages()) {
builder.addPackage(reactPackage);
}
//获取js Bundle的加载路径
String jsBundleFile = getJSBundleFile();
if (jsBundleFile != null) {
builder.setJSBundleFile(jsBundleFile);
} else {
builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName()));
}
// 创建
ReactInstanceManager reactInstanceManager = builder.build();
ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_END);
return reactInstanceManager;
}
}
  1. 接下来看 MainActivity.java
1
2
3
4
5
6
7
public class MainActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
// 返回组件名
return "TestDemo";
}
}

这里我们的 MainActivity 继承自 ReactActivity,ReactActivity作为JS页面的容器。最后我们的前端界面的内容,就是渲染到了这个容器上面。(ReactActivity 后面介绍)

应用启动流程

我们开始分析 ReactActivityReactAcivity 本身继承自 Activity,并实现了其生命周期。本质上其什么也没有做,都是委托给了 ReactActivityDelegate。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public abstract class ReactActivity extends Activity
implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {
private final ReactActivityDelegate mDelegate;
protected ReactActivity() {
mDelegate = createReactActivityDelegate();
}
// 获取渲染的 RN 组件名称
protected @Nullable String getMainComponentName() {
return null;
}
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName());
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 委托给 ReactActivityDelegate 来实现
mDelegate.onCreate(savedInstanceState);
}
}

其本身所有行为都交给了 ReactActivityDelegate 来处理,我们只需要关心 ReactActivityDelegate 即可。

ReactActivityDelegate

我们先来看,ReactActivity 的 onCreate 方法,本质上映射到了 ReactActivityDelegate 的 onCreate。

ReactActivityDelegate.onCreate(Bundle savedInstanceState)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class ReactActivityDelegate {
public ReactActivityDelegate(Activity activity, @Nullable String mainComponentName) {
mActivity = activity;
mMainComponentName = mainComponentName;
mFragmentActivity = null;
}
protected void onCreate(Bundle savedInstanceState) {
if (mMainComponentName != null) {
// 载入 app 页面
loadApp(mMainComponentName);
}
// ...开发调试配置
}
protected void loadApp(String appKey) {
if (mReactRootView != null) {
throw new IllegalStateException("Cannot loadApp while app is already running.");
}
// 创建ReactRootView作为根视图 ,它本质上是一个FrameLayout
mReactRootView = createRootView();
// 启动应用程序
mReactRootView.startReactApplication(
getReactNativeHost().getReactInstanceManager(),
appKey,
getLaunchOptions());
// mActivity.setContentView
getPlainActivity().setContentView(mReactRootView);
}
}

创建阶段主要了做了如下几个事情:

  1. 创建ReactRootView作为应用的容器,它本质上是一个FrameLayout。
  2. 调用ReactRootView.startReactApplication()进一步执行应用启动流程。
  3. 调用Activity.setContentView() 将创建的 ReactRootView 作为 ReactActivity的content view。

所以呢,RN 其实被渲染到了一个 ReactRootView 上面,他可以被用在 Android 任何地方(比如 RN 视图和 原生视图组合)。接下来我们看启动过程 startReactApplication

ReactRootView.startReactApplication(ReactInstanceManager reactInstanceManager, String moduleName, @Nullable Bundle launchOptions)

简要代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class ReactRootView extends SizeMonitoringFrameLayout
implements RootView, MeasureSpecProvide {
public void startReactApplication(
ReactInstanceManager reactInstanceManager,
String moduleName,
@Nullable Bundle initialProperties,
@Nullable String initialUITemplate) {
try {
// 判断是否运行在主线程上
UiThreadUtil.assertOnUiThread();
mReactInstanceManager = reactInstanceManager;
mJSModuleName = moduleName;
mAppProperties = initialProperties;
mInitialUITemplate = initialUITemplate;
// 创建RN应用上下文
if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
mReactInstanceManager.createReactContextInBackground();
}
attachToReactInstanceManager();
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
}
}
}

参数信息:

  • ReactInstanceManager reactInstanceManager:ReactInstanceManager 实例
  • String moduleName:模块的名字,对应ReactActivity.getMainComponentName()与AppRegistry.registerComponent()
  • Bundle launchOptions:Bundle 类型,可以在 startActivity 时候传递参数到 JS 层

(UiThreadUtil 主要包装了两个方法:UiThreadUtil.isOnUiThread(),UiThreadUtil.runOnUiThread(Runnable runnable))

主要还是调用了 ReactInstanceManager 上的 createReactContextInBackground 方法。

ReactInstanceManager.createReactContextInBackground()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class ReactInstanceManager {
/**
* Trigger react context initialization asynchronously in a background async task. This enables
* applications to pre-load the application JS, and execute global code before
* {@link ReactRootView} is available and measured. This should only be called the first time the
* application is set up, which is enforced to keep developers from accidentally creating their
* application multiple times without realizing it.
*
* Called from UI thread.
*/
@ThreadConfined(UI)
public void createReactContextInBackground() {
Log.d(ReactConstants.TAG, "ReactInstanceManager.createReactContextInBackground()");
Assertions.assertCondition(
!mHasStartedCreatingInitialContext,
"createReactContextInBackground should only be called when creating the react " +
"application for the first time. When reloading JS, e.g. from a new file, explicitly" +
"use recreateReactContextInBackground");
mHasStartedCreatingInitialContext = true;
recreateReactContextInBackgroundInner();
}
@ThreadConfined(UI)
private void recreateReactContextInBackgroundInner() {
UiThreadUtil.assertOnUiThread();
// 这里有一大堆代码,都是在开发模式下在线更新 bundle (mDevSupportManager.handleReloadJS()),调用开发菜单等调试功能的地方
// 但是实际上都调用到了 下面那句话
if (mUseDeveloperSupport && mJSMainModulePath != null) {
}
// 线上模式
recreateReactContextInBackgroundFromBundleLoader();
}
@ThreadConfined(UI)
private void recreateReactContextInBackgroundFromBundleLoader() {
recreateReactContextInBackground(mJavaScriptExecutorFactory, mBundleLoader);
}
@ThreadConfined(UI)
private void recreateReactContextInBackground(
JavaScriptExecutorFactory jsExecutorFactory,
JSBundleLoader jsBundleLoader) {
UiThreadUtil.assertOnUiThread();
// ReactContextInitParams 类就是实现了一个断言,两个参数必须有
final ReactContextInitParams initParams = new ReactContextInitParams(
jsExecutorFactory,
jsBundleLoader);
if (mCreateReactContextThread == null) {
// 初始化一个异步任务,创建 ReactContextInitAsyncTask
runCreateReactContextOnNewThread(initParams);
} else {
// 创建ReactContext的后台任务已经开启,缓存initParams在队列中等待重新创建ReactContext
mPendingReactContextInitParams = initParams;
}
}
public ReactContextInitParams(
JavaScriptExecutorFactory jsExecutorFactory,
JSBundleLoader jsBundleLoader) {
mJsExecutorFactory = Assertions.assertNotNull(jsExecutorFactory);
mJsBundleLoader = Assertions.assertNotNull(jsBundleLoader);
}
}

这里创建过程从上到下执行,最后调用到 runCreateReactContextOnNewThread。该方法实际上就是新启了一个线程,来执行如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
final ReactApplicationContext reactApplicationContext =
createReactContext(
initParams.getJsExecutorFactory().create(),
initParams.getJsBundleLoader());
// 如果创建完毕 createContext 则回调这个线程
Runnable setupReactContextRunnable =
new Runnable() {
@Override
public void run() {
try {
setupReactContext(reactApplicationContext);
} catch (Exception e) {
mDevSupportManager.handleException(e);
}
}
};
// c++ 层回调
reactApplicationContext.runOnNativeModulesQueueThread(setupReactContextRunnable);
```
完成 ReactApplicationContext 的创建。我们看传入的两个参数:
* JsExecutorFactory jsExecutor:当该类被加载时,它会自动去加载"reactnativejnifb.so"库,并会调用 Native 方
法 initHybrid() 初始化 C++层 RN 与 JSC通信的框架。
* JSBundleLoader jsBundleLoader:缓存了JSBundle的信息,封装了上层加载JSBundle的相关接口,CatalystInstance通过其间接调用ReactBridge 去加载J S文件,不同的场景会创建不同的加载器,具体可以查看类JSBundleLoader。
##### ReactInstanceManager.createReactContext( JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader)
简要代码如下
```java
public class ReactInstanceManager {
private ReactApplicationContext createReactContext(
JavaScriptExecutor jsExecutor,
JSBundleLoader jsBundleLoader) {
// ReactApplicationContext 是 ReactContext的包装类。实际上调用的就是 ReactContext。
final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);
NativeModuleCallExceptionHandler exceptionHandler = mNativeModuleCallExceptionHandler != null
? mNativeModuleCallExceptionHandler
: mDevSupportManager;
reactContext.setNativeModuleCallExceptionHandler(exceptionHandler);
// 创建 JavaModule 注册表Builder,用来创建JavaModule注册表,JavaModule注册表将所有的JavaModule注册到CatalystInstance中。
// mPackages 就是 ReactNativeHost 那里 getPackages 的各种模块 ReactPackage
NativeModuleRegistry nativeModuleRegistry = processPackages(reactContext, mPackages, false);
// 创建 CatalystInstance
CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
.setJSExecutor(jsExecutor)
.setRegistry(nativeModuleRegistry)
.setJSBundleLoader(jsBundleLoader)
.setNativeModuleCallExceptionHandler(exceptionHandler);
final CatalystInstance catalystInstance;
try {
catalystInstance = catalystInstanceBuilder.build();
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_END);
}
if (mJSIModulePackage != null) {
catalystInstance.addJSIModules(mJSIModulePackage
.getJSIModules(reactContext, catalystInstance.getJavaScriptContextHolder()));
}
if (mBridgeIdleDebugListener != null) {
catalystInstance.addBridgeIdleDebugListener(mBridgeIdleDebugListener);
}
// 通过CatalystInstance开始加载JS Bundle
// runJSBundle 在 CatalysInstanceImp 中
catalystInstance.runJSBundle();
// 关联ReacContext与CatalystInstance
reactContext.initializeWithInstance(catalystInstance);
return reactContext;
}
}
  1. 主要创建 JavaModule 表,交给 CatalystInstance 管理
  2. 处理ReactPackage,将JavaModule与JavaScriptModule放进各自对应的注册表里。
  3. 通过上面jsExecutor、nativeModuleRegistry、jsModulesRegistry、jsBundleLoader、exceptionHandler等参数创建CatalystInstance实例。
  4. 关联 ReactContext 与 CatalystInstance,并将JS Bundle加载进来,等待ReactContextInitAsyncTask结束以后调用JS入口渲染页面。
  5. 最后调用 CatalystInstance.runJSBundle()去加载 JS Bundle

最终由 C++ 中的JSCExecutor.cpp 完成了 JS Bundle 的加载。
这里起到作用的就是 CatalystInstance 他由 CatalystInstanceImpl 构造而成。查看代码:

CatalystInstanceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class CatalystInstanceImpl implements CatalystInstance {
// C++ parts
private final HybridData mHybridData;
private native static HybridData initHybrid();
// 在C++层初始化通信桥ReactBridge
private native void initializeBridge(
ReactCallback callback,
JavaScriptExecutor jsExecutor,
MessageQueueThread jsQueue,
MessageQueueThread moduleQueue,
Collection<JavaModuleWrapper> javaModules,
Collection<ModuleHolder> cxxModules);
private CatalystInstanceImpl(
final ReactQueueConfigurationSpec reactQueueConfigurationSpec,
final JavaScriptExecutor jsExecutor,
final NativeModuleRegistry nativeModuleRegistry,
final JSBundleLoader jsBundleLoader,
NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) {
// Native方法,用来创建JNI相关状态,并返回mHybridData。
mHybridData = initHybrid();
// RN中的三个线程:Native Modules Thread、JS Thread、UI Thread,都是通过Handler来管理的。
mReactQueueConfiguration = ReactQueueConfigurationImpl.create(
reactQueueConfigurationSpec,
new NativeExceptionHandler());
mBridgeIdleListeners = new CopyOnWriteArrayList<>();
mNativeModuleRegistry = nativeModuleRegistry;
mJSModuleRegistry = new JavaScriptModuleRegistry();
mJSBundleLoader = jsBundleLoader;
mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler;
mNativeModulesQueueThread = mReactQueueConfiguration.getNativeModulesQueueThread();
mTraceListener = new JSProfilerTraceListener(this);
// Native方法,调用initializeBridge()方法,并创建BridgeCallback实例,初始化Bridge。
initializeBridge(
new BridgeCallback(this),
jsExecutor,
mReactQueueConfiguration.getJSQueueThread(),
mNativeModulesQueueThread,
mNativeModuleRegistry.getJavaModules(this),
mNativeModuleRegistry.getCxxModules());
mJavaScriptContextHolder = new JavaScriptContextHolder(getJavaScriptContext());
}
}
  • ReactCallback callback:CatalystInstanceImpl的静态内部类ReactCallback,负责接口回调。
  • JavaScriptExecutor jsExecutor:JS执行器,将JS的调用传递给C++层。
  • MessageQueueThread jsQueue.getJSQueueThread():JS线程,通过mReactQueueConfiguration.getJSQueueThread()获得,
  • Collection javaModules:java modules,来源于mJavaRegistry.getJavaModules(this)。
  • Collection cxxModules):c++ modules,来源于mJavaRegistry.getCxxModules()。

CatalystInstanceImpl 创建好,调用 runJSBundle 来加载js

CatalystInstanceImpl.runJSBundle()

这个代码最后会调用,初始化创建 ReactInstanceManager -> createReactContext 传入的 JSBundleLoader bundleLoader 上的

1
2
// 调用加载器加载JS Bundle,不同情况下加载器各不相同。
mJSBundleLoader.loadScript(CatalystInstanceImpl.this);

bundleLoader 由 ReactInstanceManagerBuilder.setJSBundleFile(String jsBundleFile) 创建而来

1
2
3
4
5
6
7
8
9
10
11
12
13
public ReactInstanceManagerBuilder setJSBundleFile(String jsBundleFile) {
if (jsBundleFile.startsWith("assets://")) {
mJSBundleAssetUrl = jsBundleFile;
mJSBundleLoader = null;
return this;
}
return setJSBundleLoader(JSBundleLoader.createFileLoader(jsBundleFile));
}
public ReactInstanceManagerBuilder setJSBundleLoader(JSBundleLoader jsBundleLoader) {
mJSBundleLoader = jsBundleLoader;
mJSBundleAssetUrl = null;
return this;
}

JSBundleLoader 提供了多种加载方案,通过 ReactInstanceManagerBuilder.setJSBundleFile(String jsBundleFile) 调用的加载器如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public abstract class JSBundleLoader {
public static JSBundleLoader createFileLoader(final String fileName) {
return createFileLoader(fileName, fileName, false);
}
public static JSBundleLoader createFileLoader(
final String fileName,
final String assetUrl,
final boolean loadSynchronously) {
return new JSBundleLoader() {
@Override
public String loadScript(CatalystInstanceImpl instance) {
instance.loadScriptFromFile(fileName, assetUrl, loadSynchronously);
return fileName;
}
};
}
/** Loads the script, returning the URL of the source it loaded. */
public abstract String loadScript(CatalystInstanceImpl instance);
}

可以看到,在这种加载器下,最后调用的是 CatalystInstanceImpl 上的 loadScriptFromFile

1
2
3
4
5
6
7
8
public class CatalystInstanceImpl implements CatalystInstance {
private native void jniLoadScriptFromFile(String fileName, String sourceURL, boolean loadSynchronously);
void loadScriptFromFile(String fileName, String sourceURL, boolean loadSynchronously) {
mSourceURL = sourceURL;
// C++ 方法
jniLoadScriptFromFile(fileName, sourceURL, loadSynchronously);
}
}

CatalystInstanceImpl.java 最终还是调用C++层的 CatalystInstanceImpl.cpp去加载JS Bundle。

接下来就是 C++ 部分了,不太会了呢。

ReactInstanceManager.setupReactContext(final ReactApplicationContext reactContext)

createContext 调用完毕后,C++ 会回调了 setupReactContextRunnable 线程,该线程调用的就是 setupReactContext 方法。代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class ReactInstanceManager {
private void setupReactContext(final ReactApplicationContext reactContext) {
Log.d(ReactConstants.TAG, "ReactInstanceManager.setupReactContext()");
ReactMarker.logMarker(PRE_SETUP_REACT_CONTEXT_END);
ReactMarker.logMarker(SETUP_REACT_CONTEXT_START);
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "setupReactContext");
synchronized (mAttachedRootViews) {
synchronized (mReactContextLock) {
mCurrentReactContext = Assertions.assertNotNull(reactContext);
}
CatalystInstance catalystInstance =
Assertions.assertNotNull(reactContext.getCatalystInstance());
// 执行Native Java module的初始化
catalystInstance.initialize();
// 重置DevSupportManager的ReactContext
mDevSupportManager.onNewReactContextCreated(reactContext);
// 内存状态回调设置
mMemoryPressureRouter.addMemoryPressureListener(catalystInstance);
// 复位生命周期 (和这个有关 LifecycleState.RESUMED)
moveReactContextToCurrentLifecycleState();
ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_START);
for (ReactRootView rootView : mAttachedRootViews) {
attachRootViewToInstance(rootView);
}
ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_END);
}
ReactInstanceEventListener[] listeners =
new ReactInstanceEventListener[mReactInstanceEventListeners.size()];
final ReactInstanceEventListener[] finalListeners =
mReactInstanceEventListeners.toArray(listeners);
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
for (ReactInstanceEventListener listener : finalListeners) {
listener.onReactContextInitialized(reactContext);
}
}
});
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
ReactMarker.logMarker(SETUP_REACT_CONTEXT_END);
reactContext.runOnJSQueueThread(
new Runnable() {
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
ReactMarker.logMarker(CHANGE_THREAD_PRIORITY, "js_default");
}
});
reactContext.runOnNativeModulesQueueThread(
new Runnable() {
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
}
});
}
}

ReactInstanceManager.attachRootViewToInstance 方法,重置 ReactRootView 内容,然后将ReactRootView作为根布局,作为根布局进行绘制。随后调用 rootView.setRootViewTag(rootTag); 设置内相关内容,调用 rootView.runApplication() 启动 js。

rootView.runApplication 里面就是包装了一些启动参数 launchOptions 与 模块名 jsAppModuleName。然后最终调用了

catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams) 方法:

检查下这个代码:

1
2
3
4
5
6
7
8
9
/**
* JS module interface - main entry point for launching React application for a given key.
*/
public interface AppRegistry extends JavaScriptModule {
void runApplication(String appKey, WritableMap appParameters);
void unmountApplicationComponentAtRootTag(int rootNodeTag);
void startHeadlessTask(int taskId, String taskKey, WritableMap data);
}

根据注释我们知道这有可能就是js层暴露给java的接口方法。?? (AppRegister.js)