第一次接触 React Native 是在四年前实习的时候,当时在项目中使用的 RN 版本是 0.28.x
,间隔四年之后,再次在项目中使用 RN 时版本已是 0.57.x
。在撰写本文时,RN 的版本是 0.60.4
,所以,本文将以 0.60.4
版本为基础,简要分析 RN 应用在 Android 平台上的启动流程
。
用 RN 来写一个 Hello World 应用非常简单。通过 RN cli 生成项目之后,更改程序的入口文件即可:
import { Text, AppRegistry } from 'react-native' import App from './App' // ... AppRegistry.registerComponent('HelloWorld', () => App);
程序的入口文件一般是通过 AppRegistry
对 RN 应用进行注册, registerComponent
的实现如下:
// react-native/Libraries/ReactNative/AppRegistry.js // ... // 类型声明 export type ComponentProvider = () => React$ComponentType<any>; export type Runnable = { component?: ComponentProvider, run: Function, }; export type Runnables = { [appKey: string]: Runnable, }; // 保存注册过的应用 const runnables: Runnables = {}; // ... // 注册应用的根组件 registerComponent( appKey: string, componentProvider: ComponentProvider, section?: boolean, ): string { runnables[appKey] = { componentProvider, /** * appParameters 是原生端初始化 RN 应用时透传的参数 * 属性主要包含用于初始化的 initialProps,rootTag,fabric等 */ run: appParameters => { renderApplication( // ... ) }, }; // ... return appKey; }, // ...
registerComponent
方法的第一个参数是 appKey
,第二个参数是与之对应的根组件。因而如果要注册多个 RN 应用,就需要确保 appKey
的值是唯一的,因为原生端也是依赖 appKey
来启动对应的 RN 应用的。
那么,在 JavaScript 端注册 HelloWorld
应用之后,原生端是怎么启动 HelloWorld
的呢?
通过 RN cli 新建 Hello
项目之后,不仅会生成 JavaScript 代码,也会创建与之对应的原生工程项目。对于 Android 工程而言,会生成两个主要的类: MainActivity
和 MainApplication
,这是 Android 应用的启动入口。
先看下 MainActivity
的实现:
// ... public class MainActivity extends ReactActivity { @Override protected String getMainComponentName() { return "HelloWorld"; } }
MainActivity
继承了 ReactActivity
,并重写了 getMainComponentName
方法,而这个方法就是返回在 JavaScript 端注册的 appKey
。
然后再看下 MainApplication
的实现:
// ... public class MainApplication extends Application implements ReactApplication { // 创建 ReactNativeHost 的匿名子类实例 private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { // 是否开启 dev mode return BuildConfig.DEBUG; } @Override protected List<ReactPackage> getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List<ReactPackage> packages = new PackageList(this).getPackages(); /** * 返回原生依赖的包列表 * 实际开发中,js 端会对原生端有依赖,当原生端把依赖暴露给 RN 时,需要在这手动添加原生包 * 在后续的流程中,会把所有的原生依赖在 C++ 层进行注册,供 js 端调用 * packages.add(new MyReactNativePackage()) */ return packages; } @Override protected String getJSMainModuleName() { // 返回主模块名,默认为 index return "index"; } }; @Override public ReactNativeHost getReactNativeHost() { return mReactNativeHost; } @Override public void onCreate() { super.onCreate(); /** * 初始化 Soloader(https://github.com/facebook/SoLoader) * 在一个 RN 应用中,牵涉到 js 和 Native(C/C++) 的通信(JSC/JSI),Java 和 Native(C/C++) 的通信(JNI) * 以及 js 和 Java 之间的通信(转嫁到 C++ 上) * 而 Soloader 就是一个 Native Code(主要是c/c++) 的 loader,用于加载和解析动态链接库,为后续的通信作准备 */ SoLoader.init(this, /* native exopackage */ false); } }
MainApplication
实现了接口 ReactApplication
,主要是实现其 getReactNativeHost
方法:
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactApplication.java package com.facebook.react; public interface ReactApplication { /** Get the default {@link ReactNativeHost} for this app. */ ReactNativeHost getReactNativeHost(); }
ReactNativeHost
是 RN 应用的宿主类,其本身是一个抽象类,在创建 ReactNativeHost
实例时,重写了里面的两个抽象方法:
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java // ... public abstract class ReactNativeHost { private final Application mApplication; private @Nullable ReactInstanceManager mReactInstanceManager; protected ReactNativeHost(Application application) { // 保存 app 应用实例 mApplication = application; } /** * 返回 ReactInstanceManager 实例 * 这个方法会在 ReactDelegate#loadApp 方法中被调用 * 其返回值赋值给 ReactRootView#startReactApplication 方法的第一个参数 */ public ReactInstanceManager getReactInstanceManager() { if (mReactInstanceManager == null) { // 略去日志代码 // 实例不存在则创建实例 mReactInstanceManager = createReactInstanceManager(); // 略去日志代码 } return mReactInstanceManager; } // ... // 创建 ReactInstanceManager 实例 protected ReactInstanceManager createReactInstanceManager() { ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_START); /** * 类 ReactInstanceManagerBuilder 提供了很多 set 方法来保存创建 * ReactInstanceManager 实例相关的上下文信息 */ ReactInstanceManagerBuilder builder = ReactInstanceManager.builder() // 应用上下文 .setApplication(mApplication) // 设置MainModuleName,相当于应用首页的 js bundle .setJSMainModulePath(getJSMainModuleName()) // 是否开启dev模式 .setUseDeveloperSupport(getUseDeveloperSupport()) // 设置红盒的回调(dev 模式下才有红屏显示) .setRedBoxHandler(getRedBoxHandler()) // 设置 js 的执行器工厂实例,为后续加载和解析 js bundle 作准备 .setJavaScriptExecutorFactory(getJavaScriptExecutorFactory()) // 设置UI实现机制的Provider .setUIImplementationProvider(getUIImplementationProvider()) // 设置 JSI Module:js -->C++(JSI)-->Java Module .setJSIModulesPackage(getJSIModulePackage()) // 初始化 host 的生命周期状态 .setInitialLifecycleState(LifecycleState.BEFORE_CREATE); // 添加原生依赖包 for (ReactPackage reactPackage : getPackages()) { builder.addPackage(reactPackage); } /** * 获取js Bundle的加载路径 * 如果没有自定义加载路径,就从 Android assets 中加载 index.android.bundle 文件 * 默认路径是:assets:// + getBundleAssetName 方法的返回值 */ String jsBundleFile = getJSBundleFile(); if (jsBundleFile != null) { builder.setJSBundleFile(jsBundleFile); } else { builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName())); } // 根据上面设置的一系列参数去创建 ReactInstanceManager 实例 ReactInstanceManager reactInstanceManager = builder.build(); ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_END); return reactInstanceManager; } // RedBox 相关的回调 protected @Nullable RedBoxHandler getRedBoxHandler() { return null; } // 如果要自定义 js 执行器,重写该方法 protected @Nullable JavaScriptExecutorFactory getJavaScriptExecutorFactory() { return null; } protected final Application getApplication() { return mApplication; } // 如果需要自定义UI实现机制,可重写该方法,但99%的情况下不需要,使用默认机制就行 protected UIImplementationProvider getUIImplementationProvider() { return new UIImplementationProvider(); } protected @Nullable JSIModulePackage getJSIModulePackage() { return null; } /** * 返回主模块名 * 返回值决定了从服务器拉取 js bundle 的 URL,仅在开发模式下有用 */ protected String getJSMainModuleName() { return "index.android"; } /** * 返回 js bundle 文件的路径 * 如果需要自定义路径,需要在子类中重写这个方法 * 默认会从 Android assets 中加载 js bundle * 文件路径类似于 "file://sdcard/myapp_cache/index.android.bundle" */ protected @Nullable String getJSBundleFile() { return null; } // 返回 Android assets 中的 js bundle 名称 protected @Nullable String getBundleAssetName() { return "index.android.bundle"; } // 是否开启dev模式 public abstract boolean getUseDeveloperSupport(); // 返回app需要的ReactPackage,包含了运行时需要用到的NativeModule/JavaScriptModule等 protected abstract List<ReactPackage> getPackages(); }
虽然在 ReactDelegate#loadApp
方法被调用时才创建 ReactInstanceManager
实例,但我们简单看下其创建的参数列表,这有利于后文的理解。
ReactInstanceManagerBuilder#build
方法的实现如下:
// react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java // ... import static com.facebook.react.modules.systeminfo.AndroidInfoHelpers.getFriendlyDeviceName; // ... public ReactInstanceManager build() { // ... if (mUIImplementationProvider == null) { // create default UIImplementationProvider if the provided one is null. mUIImplementationProvider = new UIImplementationProvider(); } // We use the name of the device and the app for debugging & metrics String appName = mApplication.getPackageName(); String deviceName = getFriendlyDeviceName(); return new ReactInstanceManager( mApplication, mCurrentActivity, mDefaultHardwareBackBtnHandler, mJavaScriptExecutorFactory == null ? getDefaultJSExecutorFactory(appName, deviceName) : mJavaScriptExecutorFactory, (mJSBundleLoader == null && mJSBundleAssetUrl != null) ? JSBundleLoader.createAssetLoader( mApplication, mJSBundleAssetUrl, false /*Asynchronous*/) : mJSBundleLoader, mJSMainModulePath, mPackages, mUseDeveloperSupport, mBridgeIdleDebugListener, Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set"), mUIImplementationProvider, mNativeModuleCallExceptionHandler, mRedBoxHandler, mLazyViewManagersEnabled, mDevBundleDownloadListener, mMinNumShakes, mMinTimeLeftInFrameForNonBatchedOperationMs, mJSIModulesPackage, mCustomPackagerCommandHandlers); } private JavaScriptExecutorFactory getDefaultJSExecutorFactory(String appName, String deviceName) { try { // 加载 C++ 层的 jscexecutor SoLoader.loadLibrary("jscexecutor"); return new JSCExecutorFactory(appName, deviceName); } catch (UnsatisfiedLinkError jscE) { // Otherwise use Hermes return new HermesExecutorFactory(); } } // ...
重点需要关注两点:
mJSBundleLoader
的初始化: JSBundleLoader
是一个抽象类,但根据不同的 bundle 加载场景,提供了不同的静态方法来创建匿名子类实例。上文说到,可以通过重写 ReactNativeHost#getJSBundleFile
方法自定义 bundle 的加载路径。如果 bundle 路径不是以 assets://
开头,则会通过 JSBundleLoader
类的静态方法 createFileLoader
创建一个实例;反之,则会通过其静态方法 createAssetLoader
创建一个实例。
mJavaScriptExecutorFactory
的初始化:通过上文可知, ReactNativeHost#getJavaScriptExecutorFactory
返回值是 null
,因而会调用 getDefaultJSExecutorFactory
方法创建默认的 js 执行器工厂实例。
接下来看看 ReactActivity
的实现。
从上文可知, MainActivity
继承了 ReactActivity
,并重写了 getMainComponentName
方法。 ReactActivity
是一个抽象类,其主要实现如下:
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java // ... public abstract class ReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler, PermissionAwareActivity { // 声明 ReactActivityDelegate 实例变量 private final ReactActivityDelegate mDelegate; protected ReactActivity() { // 在构造函数中创建 ReactActivityDelegate 实例 mDelegate = createReactActivityDelegate(); } // 在子类 MainActivity 中重写了该方法,返回 js 端注册的 appKey protected @Nullable String getMainComponentName() { return null; } protected ReactActivityDelegate createReactActivityDelegate() { // 创建 ReactActivityDelegate 实例 return new ReactActivityDelegate(this, getMainComponentName()); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDelegate.onCreate(savedInstanceState); } //... // 获取 ReactNativeHost 实例 protected final ReactNativeHost getReactNativeHost() { return mDelegate.getReactNativeHost(); } // 获取 ReactInstanceManager 实例 protected final ReactInstanceManager getReactInstanceManager() { return mDelegate.getReactInstanceManager(); } // 加载 RN App protected final void loadApp(String appKey) { mDelegate.loadApp(appKey); } }
ReactActivity
本身是一个抽象类,没有具体的功能实现,其主要作用有两个:
getMainComponentName
方法的声明 ReactActivityDelegate
实例,便于把具体的功能全委托给 ReactActivityDelegate
类来处理
ReactActivityDelegate
类的主要实现如下:
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java // ... public class ReactActivityDelegate { private final @Nullable Activity mActivity; private final @Nullable String mMainComponentName; // ... private ReactDelegate mReactDelegate; // 构造函数 public ReactActivityDelegate(ReactActivity activity, @Nullable String mainComponentName) { mActivity = activity; mMainComponentName = mainComponentName; } /** * 获取 bundle 初始化的 props * 如果需要初始化的 props,需要 Android 实现一个子类并重写这个方法或者自定义实现 ReactActivityDelegate * 该方法的返回值会赋值给 js 端 run 方法的参数appParameters#initialProps */ protected @Nullable Bundle getLaunchOptions() { return null; } // 获取 ReactRootView 实例 protected ReactRootView createRootView() { return mReactDelegate.createRootView(); } /** * 获取当前应用使用的 ReactNativeHost 实例 * 上文有说到,在 ReactNativeHost 的实例是在 MainApplication 中创建的 */ protected ReactNativeHost getReactNativeHost() { return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost(); } // 获取 ReactInstanceManager 实例 public ReactInstanceManager getReactInstanceManager() { return mReactDelegate.getReactInstanceManager(); } // 获取 appKey public String getMainComponentName() { return mMainComponentName; } protected void onCreate(Bundle savedInstanceState) { String mainComponentName = getMainComponentName(); // 创建 ReactDelegate 实例 mReactDelegate = new ReactDelegate( getPlainActivity(), getReactNativeHost(), mainComponentName, getLaunchOptions()); if (mMainComponentName != null) { // 开启加载应用 loadApp(mainComponentName); } } protected void loadApp(String appKey) { // 实际是调用 ReactDelegate 实例的 loadApp 方法启动 RN 应用 mReactDelegate.loadApp(appKey); // 调用Activity 的setContentView()方法,将根视图添加到当前的Activity getPlainActivity().setContentView(mReactDelegate.getReactRootView()); } // ... protected Context getContext() { return Assertions.assertNotNull(mActivity); } protected Activity getPlainActivity() { return ((Activity) getContext()); } }
ReactActivityDelegate
类主要是在其生命周期的 onCreate
方法中做了三件事:创建 ReactDelegate
实例、调用 ReactActivityDelegate#loadApp
开始启动 RN 应用以及设置当前 Activity 的根视图。
ReactDelegate
类的实现比较简单,关键部分代码如下:
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java // ... public class ReactDelegate { // ... // 构造函数 public ReactDelegate( Activity activity, ReactNativeHost reactNativeHost, @Nullable String appKey, @Nullable Bundle launchOptions) { mActivity = activity; mMainComponentName = appKey; mLaunchOptions = launchOptions; mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer(); mReactNativeHost = reactNativeHost; } // ... public void loadApp(String appKey) { if (mReactRootView != null) { throw new IllegalStateException("Cannot loadApp while app is already running."); } // 创建 RN 容器根视图 mReactRootView = createRootView(); mReactRootView.startReactApplication( // 这里会去创建 ReactInstanceManager 实例 getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions); } public ReactRootView getReactRootView() { return mReactRootView; } protected ReactRootView createRootView() { return new ReactRootView(mActivity); } // ... private ReactNativeHost getReactNativeHost() { return mReactNativeHost; } public ReactInstanceManager getReactInstanceManager() { return getReactNativeHost().getReactInstanceManager(); } }
ReactDelegate#loadApp
方法主要做了两件事:创建 RootView 和开始启动 React App。
ReactRootView
是一个自定义的 View,其父类是 FrameLayout
,代码量比较大,因而我们只顺着上面的思路看一下 startReactApplication
的实现:
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java // ... public class ReactRootView extends FrameLayout implements RootView, ReactRoot { // ... public void startReactApplication( ReactInstanceManager reactInstanceManager, String moduleName, @Nullable Bundle initialProperties, @Nullable String initialUITemplate) { // ... try { // 断言:如果当前线程不是 UI 线程的话,就会抛出 Expected to run on UI thread! 的错误 UiThreadUtil.assertOnUiThread(); Assertions.assertCondition( mReactInstanceManager == null, "This root view has already been attached to a catalyst instance manager"); // 赋值 mReactInstanceManager = reactInstanceManager; mJSModuleName = moduleName; mAppProperties = initialProperties; mInitialUITemplate = initialUITemplate; // mUseSurface 是在构造函数中被赋值的 if (mUseSurface) { // TODO initialize surface here } /** * 在后台任务中触发 react context 的初始化(异步) * 此时会去预加载 js,并在 UI 的布局完成之前执行全局代码 */ mReactInstanceManager.createReactContextInBackground(); // 将 RootView 附加到 ReactInstanceManager 的成员变量 mAttachedReactRoots 中 // 后文会再提到 mAttachedReactRoots attachToReactInstanceManager(); } finally { Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); } } // ... }
接下来我们看 ReactInstanceManager
对应代码的实现。
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java // ... public void createReactContextInBackground() { //略去日志输出代码 // UI 线程断言 UiThreadUtil.assertOnUiThread(); // 是否已经初始化的判断 if (!mHasStartedCreatingInitialContext) { mHasStartedCreatingInitialContext = true; recreateReactContextInBackgroundInner(); } } /** * Recreate the react application and context. This should be called if configuration has changed * or the developer has requested the app to be reloaded. It should only be called after an * initial call to createReactContextInBackground. */ @ThreadConfined(UI) public void recreateReactContextInBackground() { // ... recreateReactContextInBackgroundInner(); } // ...
从代码中可以看到, createReactContextInBackground
在 Application 中只会被调用一次。当应用配置或者应用重新加载时,需要重新创建 ReactContext 信息,此时是去调用 公开的
recreateReactContextInBackground
方法(注意:该方法有一个 私有的
实现,后续会提到)。但两个方法最终调用的实际都是 recreateReactContextInBackgroundInner
方法:
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java // ... private void recreateReactContextInBackgroundInner() { // ... // 断言 UiThreadUtil.assertOnUiThread(); // 开发模式 if (mUseDeveloperSupport && mJSMainModulePath != null) { final DeveloperSettings devSettings = mDevSupportManager.getDevSettings(); /** * 省略代码 * 从上面条件的判断可以得知,这里主要是处理开发模式下,会从本地的服务器加载 bundle */ } // 线上模式 recreateReactContextInBackgroundFromBundleLoader(); } @ThreadConfined(UI) private void recreateReactContextInBackgroundFromBundleLoader() { // 省略输出日志的代码 // 调用私有实现 recreateReactContextInBackground(mJavaScriptExecutorFactory, mBundleLoader); } // ... @ThreadConfined(UI) private void recreateReactContextInBackground( JavaScriptExecutorFactory jsExecutorFactory, JSBundleLoader jsBundleLoader) { // ... // 断言 UiThreadUtil.assertOnUiThread(); /** * ReactContextInitParams 是一个私有类 * 主要是初始化类的 mJsExecutorFactory 和 mJsBundleLoader * 后文会具体提到 ReactContextInitParams 类 */ final ReactContextInitParams initParams = new ReactContextInitParams(jsExecutorFactory, jsBundleLoader); if (mCreateReactContextThread == null) { // 开启新线程创建react context runCreateReactContextOnNewThread(initParams); } else { //创建 ReactContext 的后台任务已经开启,缓存initParams在队列中等待重新创建 ReactContext mPendingReactContextInitParams = initParams; } } // ...
recreateReactContextInBackground
方法的私有实现中,有两个形参: jsExecutorFactory
和 jsBundleLoader
:
接着往下看 runCreateReactContextOnNewThread
的实现:
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java // ... private void runCreateReactContextOnNewThread(final ReactContextInitParams initParams) { // ... // 创建一个新线程 mCreateReactContextThread = new Thread ( null, new Runnable () { @Override public void run () { // ... try { // 设置当前线程的优先级 Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY); // 创建 ReactContext final ReactApplicationContext reactApplicationContext = createReactContext( initParams.getJsExecutorFactory().create(), initParams.getJsBundleLoader()); mCreateReactContextThread = null; // ... Runnable setupReactContextRunnable = new Runnable() { @Override public void run() { try { // 后文会再提到这行代码 setupReactContext(reactApplicationContext); } catch (Exception e) { mDevSupportManager.handleException(e); } } }; // 开启线程运行 setupReactContextRunnable reactApplicationContext.runOnNativeModulesQueueThread(setupReactContextRunnable); UiThreadUtil.runOnUiThread(maybeRecreateReactContextRunnable); } catch (Exception e) { // ... } } } ) // 启动线程 mCreateReactContextThread.start(); } // ...
runCreateReactContextOnNewThread
方法的核心是调用 createReactContext
方法来创建 React Context:
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java // ... private ReactApplicationContext createReactContext( JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader) { // 略去日志输出代码 /** * 传入 Android Application 的实例去创建 ReactContext 实例 * ReactApplicationContext 继承自 ReactContext,仅仅是简单包装了一下 * Android Application,全部的功能都在 ReactContext 类中实现 */ final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext); // 设置 Native Module 调用的异常处理器 NativeModuleCallExceptionHandler exceptionHandler = mNativeModuleCallExceptionHandler != null ? mNativeModuleCallExceptionHandler : mDevSupportManager; reactContext.setNativeModuleCallExceptionHandler(exceptionHandler); /** * 创建 Native Module 注册表,将Java可调用的API暴露给 js * mPackages 在创建 ReactInstanceManager 实例时已被初始化 */ NativeModuleRegistry nativeModuleRegistry = processPackages(reactContext, mPackages, false); // 先处理 jsExecutor/nativeModuleRegistry/jsBundleLoader 等参数,便于后续构建 CatalystInstance 实例 CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder() // 设置 React 队列配置(UI、js、native modules 三个线程队列) .setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault()) .setJSExecutor(jsExecutor) .setRegistry(nativeModuleRegistry) .setJSBundleLoader(jsBundleLoader) .setNativeModuleCallExceptionHandler(exceptionHandler); // 略去日志输出代码 final CatalystInstance catalystInstance; try { // 创建 CatalystInstance 实例 catalystInstance = catalystInstanceBuilder.build(); } finally { // 略去日志输出代码 } // 初始化 ReactContext 的队列配置(UI、js、native modules 三个线程队列) reactContext.initializeWithInstance(catalystInstance); /** * 初始化 JSI(JavaScript Interface) * JSI & JSC 的讨论:https://github.com/react-native-community/discussions-and-proposals/issues/91 * 从上文可知,mJSIModulePackage 的值是 null */ if (mJSIModulePackage != null) { catalystInstance.addJSIModules( mJSIModulePackage.getJSIModules( reactContext, catalystInstance.getJavaScriptContextHolder())); //TurboModules : https://github.com/react-native-community/discussions-and-proposals/issues/40 if (ReactFeatureFlags.useTurboModules) { catalystInstance.setTurboModuleManager( catalystInstance.getJSIModule(JSIModuleType.TurboModuleManager)); } } // 略去日志输出代码 // 开始加载 js Bundle catalystInstance.runJSBundle(); Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); return reactContext; } // ...
createReactContext
方法主要作了如下四件事:
CatalystInstance
是一个接口类型,定义了一系列 JSC(JavaScript Core) Bridge API 接口,提供了允许(从 Java 层)调用 JS 方法的环境,同时提供了部分 Java API 供 JS 层调用,其具体实现是 CatalystInstanceImpl
类。
下一篇
我们继续接着分析 CatalystInstanceImpl
类。