ReactNative[0.60.5]源碼解析之啓動流程(Android)

接觸RN開發也快兩年的時間了,期間也開發了5、6個APP了,ReactNative的版本也在快速的迭代着,今天重新出發,從源碼解析一下App的啓動流程,此次解析基於RN 0.60.5版本。

開始之前

開始分析之前,新建一個名爲RnDemo的空項目,RN版本選擇0.60.5,通過查看項目的目錄結構中Android部分會自動爲我們生成MainActivity.java和MainApplication.java文件,我們的分析就從這兩個文件入手。

Java部分,開始上傳

1.首先看一下MainApplication文件,繼承Application並實現了ReactApplication接口,主要做一寫RN的初始化操作。

public class MainApplication extends Application implements ReactApplication {
  // 實現ReactApplication接口,創建ReactNativeHost成員變量,持有ReactInstanceManager實例,做一些初始化操作。
  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
  // 是否開啓dev調試,及一些調試工具,比如redbox(紅盒),有時我們看到的報錯
    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }
    // 返回app需要的ReactPackage,添加需要加載的模塊,這個地方就是我們在項目中添加依賴包時需要添加第三方package的地方
    @Override
    protected List<ReactPackage> getPackages() {
      @SuppressWarnings("UnnecessaryLocalVariable")
      List<ReactPackage> packages = new PackageList(this).getPackages();
      // Packages that cannot be autolinked yet can be added manually here, for example:
      // packages.add(new MyReactNativePackage());
      return packages;
    }

    @Override
    protected String getJSMainModuleName() {
      return "index";
    }
  };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
   //SoLoader:加載C++底層庫,準備解析JS。
    SoLoader.init(this, /* native exopackage */ false);
  }
}

2.接下來看一下MainActivity文件,繼承自ReactActivity,ReactActivity作爲JS頁面的真正容器

public class MainActivity extends ReactActivity {

    /**
     * Returns the name of the main component registered from JavaScript.
     * This is used to schedule rendering of the component.
     */
    @Override
    protected String getMainComponentName() {
       // 返回組件名,和js入口註冊名字一致
        return "RnDemo";
    }
}
對應的js模塊註冊名字中:
AppRegistry.registerComponent("RnDemo", () => App);

3.繼續,來看一下ReactActivity來,

public abstract class ReactActivity extends AppCompatActivity
    implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {

  private final ReactActivityDelegate mDelegate;

  protected ReactActivity() {
    mDelegate = createReactActivityDelegate();
  }
  /**
   * Called at construction time, override if you have a custom delegate implementation.
   */
  protected ReactActivityDelegate createReactActivityDelegate() {
    return new ReactActivityDelegate(this, getMainComponentName());
  }
  ...
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mDelegate.onCreate(savedInstanceState);
  }
  protected final ReactNativeHost getReactNativeHost() {
    return mDelegate.getReactNativeHost();
  }

  protected final ReactInstanceManager getReactInstanceManager() {
    return mDelegate.getReactInstanceManager();
  }

  protected final void loadApp(String appKey) {
    mDelegate.loadApp(appKey);
  }
}

從以上代碼可以看到,真正實現是在ReactActivityDelegate類中進行的。
4.繼續,我們重點看一下ReactActivityDelegate中的內容

public class ReactActivityDelegate {
  protected void onCreate(Bundle savedInstanceState) {
//mMainComponentName就是上面ReactActivity.getMainComponentName()返回的組件名
    String mainComponentName = getMainComponentName();
    if (mainComponentName != null) {
// 加載app頁面
      loadApp(mainComponentName);
    }
// 雙擊判斷工具類
    mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
  }

  protected void loadApp(String appKey) {
// 非空判斷
    if (mReactRootView != null) {
      throw new IllegalStateException("Cannot loadApp while app is already running.");
    }
//創建ReactRootView作爲根視圖,它本質上是一個FrameLayout
    mReactRootView = createRootView();
// 啓動RN應用,並完成一些初始化設置
    mReactRootView.startReactApplication(
      getReactNativeHost().getReactInstanceManager(),
      appKey,
      getLaunchOptions());
// 將ReactRootView作爲Activity的顯示view
    getPlainActivity().setContentView(mReactRootView);
  }

看看ReactActivityDelegate做了那些工作:

1.創建ReactRootView作爲根視圖
2.startReactApplication啓動RN流程
3.將ReactRootView作爲ReactActivity的內容顯示view

由此看來ReactRootView是個關鍵,進入ReactRootView類繼續看一下啓動RN的startReactApplication方法,它接受三個參數:ReactInstanceManager,appName,啓動的設置參數launchOptions,

/**
   * Schedule rendering of the react component rendered by the JS application from the given JS
   * module (@{param moduleName}) using provided {@param reactInstanceManager} to attach to the
   * JS context of that manager. Extra parameter {@param launchOptions} can be used to pass initial
   * properties for the react component.
   */
  public void startReactApplication(
      ReactInstanceManager reactInstanceManager,
      String moduleName,
      @Nullable Bundle initialProperties,
      @Nullable String initialUITemplate) {
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "startReactApplication");
    try {
      UiThreadUtil.assertOnUiThread();

      // TODO(6788889): Use POJO instead of bundle here, apparently we can't just use WritableMap
      // here as it may be deallocated in native after passing via JNI bridge, but we want to reuse
      // it in the case of re-creating the catalyst instance
      Assertions.assertCondition(
        mReactInstanceManager == null,
        "This root view has already been attached to a catalyst instance manager");
    // reactInstanceManage實例,管理React實例
      mReactInstanceManager = reactInstanceManager;
   // js註冊的name,同ReactActivity.getMainComponentName()與AppRegistry.registerComponent()放回一致
      mJSModuleName = moduleName;
   // 是Native向JS傳遞的數據,以後可能由POJO代替,默認是null,需要的話要重寫createReactActivityDelegate ,並重寫其中getLaunchOptions方法
      mAppProperties = initialProperties;
      mInitialUITemplate = initialUITemplate;

      if (mUseSurface) {
        // TODO initialize surface here
      }
    // 創建RN的上下文ReactContext
      if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
        mReactInstanceManager.createReactContextInBackground();
      }
    //寬高計算完成後添加布局監聽
      attachToReactInstanceManager();

    } finally {
      Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
    }
  }

接下來,進入ReactInstanceManger類看一下createReactContextInBackground方法,

/**
   * 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();
  }

createReactContextInBackground方法僅會在首次啓動時調用,重新加載(reloaded)app時,會調用recreateReactContextInBackground(),兩個方法都會調用recreateReactContextInBackgroundInner(),

@ThreadConfined(UI)
  private void recreateReactContextInBackgroundInner() {
    Log.d(ReactConstants.TAG, "ReactInstanceManager.recreateReactContextInBackgroundInner()");
    PrinterHolder.getPrinter()
        .logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: recreateReactContextInBackground");
  //UI線程
    UiThreadUtil.assertOnUiThread();
//開發模式,實現在線更新Bundle,晃動彈出調試菜單等功能,這一部分屬於調試功能流程。
    if (mUseDeveloperSupport && mJSMainModulePath != null) {
      final DeveloperSettings devSettings = mDevSupportManager.getDevSettings();

      // If remote JS debugging is enabled, load from dev server.
      if (mDevSupportManager.hasUpToDateJSBundleInCache() &&
          !devSettings.isRemoteJSDebugEnabled()) {
        // If there is a up-to-date bundle downloaded from server,
        // with remote JS debugging disabled, always use that.
// 調試模式,從服務器加載jsBundle
        onJSBundleLoadedFromServer(null);
        return;
      }

      if (!Systrace.isTracing(TRACE_TAG_REACT_APPS | TRACE_TAG_REACT_JS_VM_CALLS)) {
// 加載服務bundle
        if (mBundleLoader == null) {
          mDevSupportManager.handleReloadJS();
        } else {
          mDevSupportManager.isPackagerRunning(
              new PackagerStatusCallback() {
                @Override
                public void onPackagerStatusFetched(final boolean packagerIsRunning) {
                  UiThreadUtil.runOnUiThread(
                      new Runnable() {
                        @Override
                        public void run() {
                          if (packagerIsRunning) {
                            mDevSupportManager.handleReloadJS();
                          } else {
                            // If dev server is down, disable the remote JS debugging.
                            devSettings.setRemoteJSDebugEnabled(false);
                            recreateReactContextInBackgroundFromBundleLoader();
                          }
                        }
                      });
                }
              });
        }
        return;
      }
    }
    // 加載本地bundle
    recreateReactContextInBackgroundFromBundleLoader();
  }

recreateReactContextInBackgroundFromBundleLoader方法向下調用recreateReactContextInBackground方法

@ThreadConfined(UI)
  private void recreateReactContextInBackground(
//C++和JS雙向通信的中轉站
    JavaScriptExecutorFactory jsExecutorFactory,
// bundle加載器,根據ReactNativeHost中的配置決定從哪裏加載bundle文件
    JSBundleLoader jsBundleLoader) {
    Log.d(ReactConstants.TAG, "ReactInstanceManager.recreateReactContextInBackground()");
    UiThreadUtil.assertOnUiThread();
    //創建ReactContextInitParams對象
    final ReactContextInitParams initParams = new ReactContextInitParams(
      jsExecutorFactory,
      jsBundleLoader);
    if (mCreateReactContextThread == null) {
  // 在newThread實例化ReactContext
      runCreateReactContextOnNewThread(initParams);
    } else {
      mPendingReactContextInitParams = initParams;
    }
  }

 //runCreateReactContextOnNewThread()方法中內容
final ReactApplicationContext reactApplicationContext =
                      createReactContext(
                          initParams.getJsExecutorFactory().create(),
                          initParams.getJsBundleLoader());

在runCreateReactContextOnNewThread方法中,我們看到是ReactInstanceManager.createReactContext方法最終創建了ReactApplicationContext,我們繼續看createReactContext()方法,有關此方法的2個參數:

JSCJavaScriptExecutor jsExecutor:JSCJavaScriptExecutor繼承於JavaScriptExecutor,當該類被加載時,它會自動去加載"reactnativejnifb.so"庫,並會調用Native方
法initHybrid()初始化C++層RN與JSC通信的框架。
JSBundleLoader jsBundleLoader:緩存了JSBundle的信息,封裝了上層加載JSBundle的相關接口,CatalystInstance通過其簡介調用ReactBridge去加載JS文件,不同的場景會創建
不同的加載器,具體可以查看類JSBundleLoader。
private ReactApplicationContext createReactContext(
      JavaScriptExecutor jsExecutor,
      JSBundleLoader jsBundleLoader) {
    Log.d(ReactConstants.TAG, "ReactInstanceManager.createReactContext()");
    ReactMarker.logMarker(CREATE_REACT_CONTEXT_START, jsExecutor.getName());
// ReactApplicationContext 是reactContext的包裝類
    final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);

    NativeModuleCallExceptionHandler exceptionHandler = mNativeModuleCallExceptionHandler != null
        ? mNativeModuleCallExceptionHandler
        : mDevSupportManager;
    reactContext.setNativeModuleCallExceptionHandler(exceptionHandler);
//創建JavaModule註冊表Builder,用來創建JavaModule註冊表,JavaModule註冊表將所有的JavaModule註冊到CatalystInstance中。
    NativeModuleRegistry nativeModuleRegistry = processPackages(reactContext, mPackages, false);
//jsExecutor、nativeModuleRegistry、nativeModuleRegistry等各種參數處理好之後,開始構建CatalystInstanceImpl實例。
    CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
      .setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
      .setJSExecutor(jsExecutor)// js執行通信類
      .setRegistry(nativeModuleRegistry)//java模塊註冊表
      .setJSBundleLoader(jsBundleLoader)// bundle加載器
      .setNativeModuleCallExceptionHandler(exceptionHandler); // 異常處理器

    ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_START);
    // CREATE_CATALYST_INSTANCE_END is in JSCExecutor.cpp
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createCatalystInstance");
    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);
    }
    if (Systrace.isTracing(TRACE_TAG_REACT_APPS | TRACE_TAG_REACT_JS_VM_CALLS)) {
//調用CatalystInstanceImpl的Native方法把Java Registry轉換爲Json,再由C++層傳送到JS層。
      catalystInstance.setGlobalVariable("__RCTProfileIsProfiling", "true");
    }
    ReactMarker.logMarker(ReactMarkerConstants.PRE_RUN_JS_BUNDLE_START);
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "runJSBundle");
//通過CatalystInstance開始加載JS Bundle
    catalystInstance.runJSBundle();
    Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
  //關聯ReacContext與CatalystInstance
    reactContext.initializeWithInstance(catalystInstance);


    return reactContext;
  }

createReactContext方法中用catalystInstance.runJSBundle() 來加載 JS bundle

@Override
  public void runJSBundle() {
   ...省略代碼
    mJSBundleLoader.loadScript(CatalystInstanceImpl.this);
}

查看loadScript方法,參數JSBundleLoaderDelegate接口的實現類CatalystInstanceImpl,我們假設調用了loadScriptFromAssets方法,

@Override
  public void loadScriptFromAssets(AssetManager assetManager, String assetURL, boolean loadSynchronously) {
    mSourceURL = assetURL;
    jniLoadScriptFromAssets(assetManager, assetURL, loadSynchronously);
  }
private native void jniLoadScriptFromAssets(AssetManager assetManager, String assetURL, boolean loadSynchronously);

CatalystInstanceImpl.java最終還是調用C++層的CatalystInstanceImpl.cpp去加載JS Bundle。
接下來看一下CatalystInstance的實現類CatalystInstanceImpl的構造方法:

private CatalystInstanceImpl(
      final ReactQueueConfigurationSpec reactQueueConfigurationSpec,
      final JavaScriptExecutor jsExecutor,
      final NativeModuleRegistry nativeModuleRegistry,
      final JSBundleLoader jsBundleLoader,
      NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) {
    Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge.");
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createCatalystInstanceImpl");
  //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);
    Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);

    Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge before initializeBridge");
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "initializeCxxBridge");
//Native方法,調用initializeBridge()方法,並創建BridgeCallback實例,初始化Bridge。
    initializeBridge(
      new BridgeCallback(this),
      jsExecutor,
      mReactQueueConfiguration.getJSQueueThread(),
      mNativeModulesQueueThread,
      mNativeModuleRegistry.getJavaModules(this),
      mNativeModuleRegistry.getCxxModules());
    Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge after initializeBridge");
    Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);

    mJavaScriptContextHolder = new JavaScriptContextHolder(getJavaScriptContext());
  }

//在C++層初始化通信橋ReactBridge
 private native void initializeBridge(
      ReactCallback callback,
      JavaScriptExecutor jsExecutor,
      MessageQueueThread jsQueue,
      MessageQueueThread moduleQueue,
      Collection<JavaModuleWrapper> javaModules,
      Collection<ModuleHolder> cxxModules);

參數解讀:

  • ReactCallback:CatalystInstanceImpl的靜態內部類ReactCallback,負責接口回調
  • JavaScriptExecutor: js執行器,將js的調用傳給c++層
  • MessageQueueThread jsQueue:js線程
  • MessageQueueThread moduleQueue: java線程
  • javaModules: java module
  • cxxModules: c++ module

好累,😀,繼續,我們去c++層看一下,在項目的node_modules/react-native/ReactAndroid/src/main/jni/react/jni可以找到CatalystInstanceImpl.cpp
看一下CatalystInstanceImpl::jniLoadScriptFromAssets

void CatalystInstanceImpl::jniLoadScriptFromAssets(
    jni::alias_ref<JAssetManager::javaobject> assetManager,
    const std::string& assetURL,
    bool loadSynchronously) {
  const int kAssetsLength = 9;  // strlen("assets://");
//獲取source js Bundle的路徑名,這裏默認的就是index.android.bundle
  auto sourceURL = assetURL.substr(kAssetsLength);
//assetManager是Java層傳遞過來的AssetManager,調用JSLoade.cpo裏的extractAssetManager()方法,extractAssetManager()再
  //調用android/asset_manager_jni.h裏的AssetManager_fromJava()方法獲取AssetManager對象。
  auto manager = extractAssetManager(assetManager);
// 調用JSloader.cpp的loadScriptFromAssets方法,讀取js Bundle裏面的內容
  auto script = loadScriptFromAssets(manager, sourceURL);
// unbundle命令打包判斷,build.gradle默認裏是bundle打包方式。
  if (JniJSModulesUnbundle::isUnbundle(manager, sourceURL)) {
    auto bundle = JniJSModulesUnbundle::fromEntryFile(manager, sourceURL);
    auto registry = RAMBundleRegistry::singleBundleRegistry(std::move(bundle));
    instance_->loadRAMBundle(
      std::move(registry),
      std::move(script),
      sourceURL,
      loadSynchronously);
    return;
  } else if (Instance::isIndexedRAMBundle(&script)) {
    instance_->loadRAMBundleFromString(std::move(script), sourceURL);
  } else {
//bundle命令打包走此流程,instance_是Instan.h中類的實例
    instance_->loadScriptFromString(std::move(script), sourceURL, loadSynchronously);
  }
}

在項目node_modules/react-native/ReactCommon的cxxReact的NativeToJsBridge.cpp文件:

void NativeToJsBridge::loadApplication(
    std::unique_ptr<JSModulesUnbundle> unbundle,
    std::unique_ptr<const JSBigString> startupScript,
    std::string startupScriptSourceURL) {

  //獲取一個MessageQueueThread,探後在線程中執行一個Task。
  runOnExecutorQueue(
      m_mainExecutorToken,
      [unbundleWrap=folly::makeMoveWrapper(std::move(unbundle)),
       startupScript=folly::makeMoveWrapper(std::move(startupScript)),
       startupScriptSourceURL=std::move(startupScriptSourceURL)]
        (JSExecutor* executor) mutable {

    auto unbundle = unbundleWrap.move();
    if (unbundle) {
      executor->setJSModulesUnbundle(std::move(unbundle));
    }

    //executor從runOnExecutorQueue()返回的map中取得,與OnLoad中的JSCJavaScriptExecutorHolder對應,也與
    //Java中的JSCJavaScriptExecutor對應。它的實例在JSIExecutor.cpp中實現。
    executor->loadApplicationScript(std::move(*startupScript),
                                    std::move(startupScriptSourceURL));
  });
}
關於unbundle命令

<unbundle命令,使用方式和bundle命令完全相同。unbundle命令是在bundle命令的基礎上增加了一項功能,除了生成整合JS文件index.android.bundle外,還會
生成各個單獨的未整合JS文件(但會被優化),全部放在js-modules目錄下,同時會生成一個名爲UNBUNDLE的標識文件,一併放在其中。UNBUNDLE標識文件的前4個字節
固定爲0xFB0BD1E5,用於加載前的校驗。

進入項目node_modules/react-native/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp進一步調用JSIExecutor.cpp的loadApplicationScript()方法。

//解釋執行JS
runtime_->evaluateJavaScript(
      std::make_unique<BigStringBuffer>(std::move(script)), sourceURL);
  flush();

flushedQueueJS支線的是MessageQueue.js的flushedQueue()方法,此時JS已經被加載到隊列中,等待Java層來驅動它。加載完JS後,返回reactApplicationContext,我們繼續跟進它的實現。
我們回到ReactInstanceManager類的runCreateReactContextOnNewThread方法中,看到setupReactContext()方法,進入之後可以看到attachRootViewToInstance(reactRoot)方法,進入後

private void attachRootViewToInstance(final ReactRoot reactRoot) {
    Log.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()");
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "attachRootViewToInstance");
    UIManager uiManagerModule = UIManagerHelper.getUIManager(mCurrentReactContext, reactRoot.getUIManagerType());

    @Nullable Bundle initialProperties = reactRoot.getAppProperties();
    final int rootTag = uiManagerModule.addRootView(
      reactRoot.getRootViewGroup(),
      initialProperties == null ?
            new WritableNativeMap() : Arguments.fromBundle(initialProperties),
        reactRoot.getInitialUITemplate());
    reactRoot.setRootViewTag(rootTag);
  // 啓動入口
    reactRoot.runApplication();
    Systrace.beginAsyncSection(
      TRACE_TAG_REACT_JAVA_BRIDGE,
      "pre_rootView.onAttachedToReactInstance",
      rootTag);
    UiThreadUtil.runOnUiThread(
        new Runnable() {
          @Override
          public void run() {
            Systrace.endAsyncSection(
                TRACE_TAG_REACT_JAVA_BRIDGE, "pre_rootView.onAttachedToReactInstance", rootTag);
            reactRoot.onStage(ReactStage.ON_ATTACH_TO_INSTANCE);
          }
        });
    Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
  }

catalystInstance.getJSModule(AppRegistry.class)AppRegistry.class是JS層暴露給Java層的接口方法,它的真正實現在AppRegistry.js裏,AppRegistry.js是運行所有RN應用的JS層入口,

runApplication(appKey: string, appParameters: any): void {
    const msg =
      'Running application "' +
      appKey +
      '" with appParams: ' +
      JSON.stringify(appParameters) +
      '. ' +
      '__DEV__ === ' +
      String(__DEV__) +
      ', development-level warning are ' +
      (__DEV__ ? 'ON' : 'OFF') +
      ', performance optimizations are ' +
      (__DEV__ ? 'OFF' : 'ON');
    infoLog(msg);
    BugReporting.addSource(
      'AppRegistry.runApplication' + runCount++,
      () => msg,
    );
    invariant(
      runnables[appKey] && runnables[appKey].run,
      'Application ' +
        appKey +
        ' has not been registered.\n\n' +
        "Hint: This error often happens when you're running the packager " +
        '(local dev server) from a wrong folder. For example you have ' +
        'multiple apps and the packager is still running for the app you ' +
        'were working on before.\nIf this is the case, simply kill the old ' +
        'packager instance (e.g. close the packager terminal window) ' +
        'and start the packager in the correct app folder (e.g. cd into app ' +
        "folder and run 'npm start').\n\n" +
        'This error can also happen due to a require() error during ' +
        'initialization or failure to call AppRegistry.registerComponent.\n\n',
    );

    SceneTracker.setActiveScene({name: appKey});
    runnables[appKey].run(appParameters);
  },

😀,基本到這,就會去調用JS進行組件渲染,再通過Java層的UIManagerModule將JS組件轉換爲Android組件,最終顯示在ReactRootView上,即完成啓動過程。😀
閱讀源代碼還是挺耗時的事情,哈哈。

同步更新至個人公衆號及網站。
個人網站:https://wayne214.github.io
CSDN:https://blog.csdn.net/wayne214
公衆號:君偉說。
個人微信公衆號.jpg

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章