美文网首页
ReactNative的启动流程精讲(基于ReactNative

ReactNative的启动流程精讲(基于ReactNative

作者: Frewen_Wong | 来源:发表于2020-04-15 23:26 被阅读0次

    title: ReactNative的启动流程精讲(基于ReactNative0.61.5)
    date: 2020-03-13 21:00:02
    tags: ReactNative;Android;


    ReactNative的启动流程精讲(基于ReactNative0.61.5)

    文章参考:https://github.com/sucese/react-native/blob/master/doc/ReactNative%E6%BA%90%E7%A0%81%E7%AF%87/3ReactNative%E6%BA%90%E7%A0%81%E7%AF%87%EF%BC%9A%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B.md

    文章参考:https://www.jianshu.com/p/baff68f85d41

    创建ReactNativeHost

    ReactNative的启动流程,我们首先看Application中的代码,实例化ReactNativeHost。ReactNativeHost主要的工作就是创建了ReactInstanceManager,它将一些信息传递给了ReactInstanceManager。同时,我们看一下ReactNativeHost的提供的方法。

    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())
              //自定义UI实现机制,这个我们一般用不到
              .setUIImplementationProvider(getUIImplementationProvider())
              .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()));
            }
            return builder.build();
          }
    }
    

    下面是ReactNativeHost提供的一些方法:

    protected @Nullable RedBoxHandler getRedBoxHandler();
    protected @Nullable JavaScriptExecutorFactory getJavaScriptExecutorFactory();
    protected final Application getApplication();
    protected UIImplementationProvider getUIImplementationProvider();
    
    

    实例化ReactActivityDelegate:

    启动ReactActivity的子类实例,在这个Activty的启动流程中,正式开始我们ReactNative启动和加载流程。
    我们先来分析一下ReactActivityDelegate。我么可以看到ReactActivityDelegate的一些提供的方法。就知道这个类的一些职责。他主要就是Activity的宿主的一些生命周期的委托调用。也就是所有ReactNative和宿主Activity的关联都是通过这个类类简历联系的。

    当然我们也看到。其实所有的生命周期的方法。这个类要么委托给ReactDelegate。要么就是直接ReactInstanceManager进行处理。所以这个类的职责也是非常简单的。

    可以说ReactNative和她的宿主Activity达到了很好的解耦。

    public abstract class ReactActivity extends AppCompatActivity
        implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {
    
      private final ReactActivityDelegate mDelegate;
    
      protected ReactActivity() {
        mDelegate = createReactActivityDelegate();
      }
    
      /**
       * Returns the name of the main component registered from JavaScript. This is used to schedule
       * rendering of the component. e.g. "MoviesApp"
       */
      protected @Nullable String getMainComponentName() {
        return null;
      }
    
      /** Called at construction time, override if you have a custom delegate implementation. */
      protected ReactActivityDelegate createReactActivityDelegate() {
        return new ReactActivityDelegate(this, getMainComponentName());
      }
      .......
    }
    

    这个类很简单,就是实例化的一个Activity的委托对象。然后所有的生命周期调用全部使用ReactActivityDelegate的代理对象完成。

    那么下面,我们看一下这个类的实现。

    public ReactActivityDelegate(ReactActivity activity, @Nullable String mainComponentName) {
        Log.d(TAG, "第二步:FMsg: 实例化ReactActivityDelegate called with: activity = [" + activity + "], mainComponentName = [" + mainComponentName + "]");
        mActivity = activity;
        mMainComponentName = mainComponentName;
      }
    

    我们看一下。Activity的onCreate的方法的代理实现。

    实例化ReactDelegate

    protected void onCreate(Bundle savedInstanceState) {
        String mainComponentName = getMainComponentName();
        mReactDelegate =
            new ReactDelegate(
                getPlainActivity(), getReactNativeHost(), mainComponentName, getLaunchOptions()) {
              @Override
              protected ReactRootView createRootView() {
                return ReactActivityDelegate.this.createRootView();
              }
            };
        //mMainComponentName就是上面ReactActivity.getMainComponentName()返回的组件名    
        if (mMainComponentName != null) {
          //载入app页面
          loadApp(mainComponentName);
        }
      }
    

    这个方法一个,实例化ReactDelegate对象。二是调用loadApp的方法。

    我们来看一下ReactDelegate的这个对象。他的职责到底是什么呢??

    protected void loadApp(String appKey) {
        mReactDelegate.loadApp(appKey);
        getPlainActivity().setContentView(mReactDelegate.getReactRootView());
      }
    

    这个方法很简单。还是调用了ReactDelegate的loadApp方法。至此位置ReactActivityDelegate的启动流程中的职责也就告一段落。下面我们看一下ReactDelegate里面的loadApp

      public void loadApp(String appKey) {
        if (mReactRootView != null) {
          throw new IllegalStateException("Cannot loadApp while app is already running.");
        }
        //创建ReactRootView作为根视图,它本质上是一个FrameLayout
        mReactRootView = createRootView();、
        //启动RN应用.这个地方我们要注意下。ReactInstanceManager就是从这个地方开始实例化的。
        mReactRootView.startReactApplication(
            getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions);
      }
    

    最终这个方法是调用到ReactRootView。这个View我们知道,其实就是我们通过setContentView设置给Activity宿主的FameLayout

    实例化ReactInstanceManager

    我们可以从代码中看到,在startReactApplication的时候,我们通过ReactNativeHost的实例化对象来获取ReactInstanceManager

     /** Get the current {@link ReactInstanceManager} instance, or create one. */
      public ReactInstanceManager getReactInstanceManager() {
        if (mReactInstanceManager == null) {
          ReactMarker.logMarker(ReactMarkerConstants.GET_REACT_INSTANCE_MANAGER_START);
          mReactInstanceManager = createReactInstanceManager();
          ReactMarker.logMarker(ReactMarkerConstants.GET_REACT_INSTANCE_MANAGER_END);
        }
        return mReactInstanceManager;
      }
      
      
      protected ReactInstanceManager createReactInstanceManager() {
        ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_START);
        Log.d(TAG, "FMsg:第五步:createReactInstanceManager() called");
        ReactInstanceManagerBuilder builder =
            ReactInstanceManager.builder()
                .setApplication(mApplication)
                 // 设置JSMain的根路径地址。也就是index.js  //"index.android"
                .setJSMainModulePath(getJSMainModuleName())
                .setUseDeveloperSupport(getUseDeveloperSupport())
                //红盒的回调
                .setRedBoxHandler(getRedBoxHandler())
                // 获取JS执行引擎的工作累的方法。默认是JSC。当然我们也可以自定义设置成V8的引擎
                // 如果需要自定义设置,那么Application中重写这个方法
                .setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
                 //自定义UI实现机制,这个我们一般用不到
                .setUIImplementationProvider(getUIImplementationProvider())
                .setJSIModulesPackage(getJSIModulePackage())
                .setInitialLifecycleState(LifecycleState.BEFORE_CREATE);
        // 类实例化的作用就是传递给ReactInstanceManager所有的Packages
        Log.i(TAG, "FMsg:第五步:createReactInstanceManager: addPackage  size = " + getPackages().size());
        // 这个使我们Application实例化的时候,我们提供的ReactPackage
        for (ReactPackage reactPackage : getPackages()) {
          builder.addPackage(reactPackage);
        }
    
        String jsBundleFile = getJSBundleFile();
        Log.i(TAG, "FMsg:第五步:createReactInstanceManager: jsBundleFile = "+jsBundleFile);
        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;
      }
    
     
    

    其实从这个地方。ReactNativeHost的历史使命就完成了。所有我们复写的他的提供方法都是在这个地方传递给ReactInstance的构造化实例对象。

    下面,我们来看一下ReactInstanceManager的构造函数

     /* package */ ReactInstanceManager(
          Context applicationContext,
          @Nullable Activity currentActivity,
          @Nullable DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler,
          JavaScriptExecutorFactory javaScriptExecutorFactory,
          @Nullable JSBundleLoader bundleLoader,
          @Nullable String jsMainModulePath,
          List<ReactPackage> packages,
          boolean useDeveloperSupport,
          @Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener,
          LifecycleState initialLifecycleState,
          @Nullable UIImplementationProvider mUIImplementationProvider,
          NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler,
          @Nullable RedBoxHandler redBoxHandler,
          boolean lazyViewManagersEnabled,
          @Nullable DevBundleDownloadListener devBundleDownloadListener,
          int minNumShakes,
          // 这个参数也比较重要,这个参数就是ReactNative的刷新帧的频率。默认-1.表示直接使用Android的刷新帧频率
          int minTimeLeftInFrameForNonBatchedOperationMs,
          @Nullable JSIModulePackage jsiModulePackage,
          @Nullable Map<String, RequestHandler> customPackagerCommandHandlers) {
        Log.d(ReactConstants.TAG, "ReactInstanceManager.ctor()");
        Log.d(TAG, "FMsg:第五步:ReactInstanceManager() called with: currentActivity = [" + currentActivity + "], defaultHardwareBackBtnHandler = [" + defaultHardwareBackBtnHandler + "], javaScriptExecutorFactory = [" + javaScriptExecutorFactory + "], bundleLoader = [" + bundleLoader + "], jsMainModulePath = [" + jsMainModulePath + "], packages = [" + packages + "], useDeveloperSupport = [" + useDeveloperSupport + "], bridgeIdleDebugListener = [" + bridgeIdleDebugListener + "], initialLifecycleState = [" + initialLifecycleState + "], mUIImplementationProvider = [" + mUIImplementationProvider + "], nativeModuleCallExceptionHandler = [" + nativeModuleCallExceptionHandler + "], redBoxHandler = [" + redBoxHandler + "], lazyViewManagersEnabled = [" + lazyViewManagersEnabled + "], devBundleDownloadListener = [" + devBundleDownloadListener + "], minNumShakes = [" + minNumShakes + "], minTimeLeftInFrameForNonBatchedOperationMs = [" + minTimeLeftInFrameForNonBatchedOperationMs + "], jsiModulePackage = [" + jsiModulePackage + "], customPackagerCommandHandlers = [" + customPackagerCommandHandlers + "]");
        initializeSoLoaderIfNecessary(applicationContext);
    
        DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(applicationContext);
    
        mApplicationContext = applicationContext;
        mCurrentActivity = currentActivity;
        mDefaultBackButtonImpl = defaultHardwareBackBtnHandler;
        // 其实默认传入的null  如果我们想使用其他JS引擎,比如V8.我们可以在这里面进行传入
        mJavaScriptExecutorFactory = javaScriptExecutorFactory;
        mBundleLoader = bundleLoader;
        mJSMainModulePath = jsMainModulePath;
        mPackages = new ArrayList<>();
        mUseDeveloperSupport = useDeveloperSupport;
        Systrace.beginSection(
            Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstanceManager.initDevSupportManager");
        mDevSupportManager =
            DevSupportManagerFactory.create(
                applicationContext,
                createDevHelperInterface(),
                mJSMainModulePath,
                useDeveloperSupport,
                redBoxHandler,
                devBundleDownloadListener,
                minNumShakes,
                customPackagerCommandHandlers);
        Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
        mBridgeIdleDebugListener = bridgeIdleDebugListener;
        mLifecycleState = initialLifecycleState;
        mMemoryPressureRouter = new MemoryPressureRouter(applicationContext);
        mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler;
    
        /// 这个地方就是添加ReactPackage
        synchronized (mPackages) {
          PrinterHolder.getPrinter()
              .logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: Use Split Packages");
          // 这个方法很重要,这个方法我们会将系统内置的那些CoreModulesPackage添加进去
          // AndroidInfoModule.class,
          // DeviceEventManagerModule.class,
          // DeviceInfoModule.class,
          // DevSettingsModule.class,
          // ExceptionsManagerModule.class,
          // HeadlessJsTaskSupportModule.class,
          // SourceCodeModule.class,
          // Timing.class,
          // UIManagerModule.class
          mPackages.add(
              new CoreModulesPackage(
                  this,
                  new DefaultHardwareBackBtnHandler() {
                    @Override
                    public void invokeDefaultOnBackPressed() {
                      ReactInstanceManager.this.invokeDefaultOnBackPressed();
                    }
                  },
                  mUIImplementationProvider,
                  lazyViewManagersEnabled,
                  minTimeLeftInFrameForNonBatchedOperationMs));
          if (mUseDeveloperSupport) {
            mPackages.add(new DebugCorePackage());
          }
          mPackages.addAll(packages);
        }
        mJSIModulePackage = jsiModulePackage;
    
        // Instantiate ReactChoreographer in UI thread.
        // 这个就是实例化Android的序列帧的监听对象
        ReactChoreographer.initialize();
        if (mUseDeveloperSupport) {
          mDevSupportManager.startInspector();
        }
      }
    

    从ReactInstanceManager的构造函数,我们可以看到。所有ReactNative的启动的初始化资源基本都已经准备完毕。所以startReactApplication的方法。我们必须要传入ReactInstanceManager实例化对象。

    其实通过查看ReactInstance的类的内容,我们可以看到这个类的方法其实也是比较简单的。他的关于启动流程最大的一个作用就是创建ReactContext。那么这个创建ReactContext是什么开始的呢?

    我们来继续看ReactRootView的startReactApplication方法。

    startReactApplication

      @ThreadConfined(UI)
      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");
    
          mReactInstanceManager = reactInstanceManager;
          mJSModuleName = moduleName;
          mAppProperties = initialProperties;
          mInitialUITemplate = initialUITemplate;
    
          if (mUseSurface) {
            // TODO initialize surface here
          }
          //创建RN上下文上下文对象
          mReactInstanceManager.createReactContextInBackground();
          //attachToReactInstanceManager 调用的是mReactInstanceManager.attachRootView(this)
          attachToReactInstanceManager();
    
        } finally {
          Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
        }
      }
    

    这个方法比较深,我们可以一步步往下看。进入到这个方法,就进入到ReactInstance的核心功能。也是ReactNative启动的核心流程。也是最重要的流程中。createReactContext的创建流程。

    @ThreadConfined(UI)
      public void createReactContextInBackground() {
        Log.d(ReactConstants.TAG, "ReactInstanceManager.createReactContextInBackground()");
        Log.d(TAG, "FMsg:第六步:ReactRootView开始创建ReactContext createReactContextInBackground() called");
        UiThreadUtil
            .assertOnUiThread(); // Assert before setting mHasStartedCreatingInitialContext = true
        if (!mHasStartedCreatingInitialContext) {
          mHasStartedCreatingInitialContext = true;
          recreateReactContextInBackgroundInner();
        }
      }
      
      
       @ThreadConfined(UI)
      private void recreateReactContextInBackgroundInner() {
        Log.d(ReactConstants.TAG, "ReactInstanceManager.recreateReactContextInBackgroundInner()");
        Log.d(TAG, "FMsg:第六步:调用内部方法recreateReactContextInBackgroundInner() called");
        PrinterHolder.getPrinter()
            .logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: recreateReactContextInBackground");
        UiThreadUtil.assertOnUiThread();
        // 调试相关的逻辑,咱们暂时忽略
        if (mUseDeveloperSupport && mJSMainModulePath != null) {
          final DeveloperSettings devSettings = mDevSupportManager.getDevSettings();
    
          if (!Systrace.isTracing(TRACE_TAG_REACT_APPS | TRACE_TAG_REACT_JS_VM_CALLS)) {
            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 (mDevSupportManager.hasUpToDateJSBundleInCache()
                                  && !devSettings.isRemoteJSDebugEnabled()) {
                                // If there is a up-to-date bundle downloaded from server,
                                // with remote JS debugging disabled, always use that.
                                onJSBundleLoadedFromServer(null);
                              } else {
                                // If dev server is down, disable the remote JS debugging.
                                devSettings.setRemoteJSDebugEnabled(false);
                                recreateReactContextInBackgroundFromBundleLoader();
                              }
                            }
                          });
                    }
                  });
            }
            return;
          }
        }
    
        recreateReactContextInBackgroundFromBundleLoader();
      }
      
      
       @ThreadConfined(UI)
      private void recreateReactContextInBackgroundFromBundleLoader() {
        Log.d(
            ReactConstants.TAG,
            "ReactInstanceManager.recreateReactContextInBackgroundFromBundleLoader()");
        Log.d(TAG, "FMsg:第六步:线上环境来将会使用后台任务创建ReactContext recreateReactContextInBackgroundFromBundleLoader() called");
        PrinterHolder.getPrinter()
            .logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: load from BundleLoader");
        recreateReactContextInBackground(mJavaScriptExecutorFactory, mBundleLoader);
      }
      
      
        @ThreadConfined(UI)
      private void runCreateReactContextOnNewThread(final ReactContextInitParams initParams) {
        Log.d(ReactConstants.TAG, "ReactInstanceManager.runCreateReactContextOnNewThread()");
        Log.d(TAG, "FMsg:第六步:runCreateReactContextOnNewThread() called with: initParams = [" + initParams + "]");
        UiThreadUtil.assertOnUiThread();
        synchronized (mAttachedReactRoots) {
          synchronized (mReactContextLock) {
            // 生命周期的回收,主要是针对可能会造成的多次初始化RN环境的
            if (mCurrentReactContext != null) {
              tearDownReactContext(mCurrentReactContext);
              mCurrentReactContext = null;
            }
          }
        }
    
        mCreateReactContextThread =
            new Thread(
                null,
                new Runnable() {
                  @Override
                  public void run() {
                    ReactMarker.logMarker(REACT_CONTEXT_THREAD_END);
                    synchronized (ReactInstanceManager.this.mHasStartedDestroying) {
                      while (ReactInstanceManager.this.mHasStartedDestroying) {
                        try {
                          ReactInstanceManager.this.mHasStartedDestroying.wait();
                        } catch (InterruptedException e) {
                          continue;
                        }
                      }
                    }
                    // As destroy() may have run and set this to false, ensure that it is true before we
                    // create
                    mHasStartedCreatingInitialContext = true;
    
                    try {
                      Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
                      ReactMarker.logMarker(VM_INIT);
                      Log.i(TAG, "FMsg:第六步:runCreateReactContextOnNewThread run: " + Thread.currentThread().getName());
                      final ReactApplicationContext reactApplicationContext =
                          createReactContext(
                              initParams.getJsExecutorFactory().create(),
                              initParams.getJsBundleLoader());
    
                      mCreateReactContextThread = null;
                      ReactMarker.logMarker(PRE_SETUP_REACT_CONTEXT_START);
    
                      // 这个地方也是一个保护机制,我们暂时不需要关注
                      final Runnable maybeRecreateReactContextRunnable =
                          new Runnable() {
                            @Override
                            public void run() {
                              if (mPendingReactContextInitParams != null) {
                                runCreateReactContextOnNewThread(mPendingReactContextInitParams);
                                mPendingReactContextInitParams = null;
                              }
                            }
                          };
                      Runnable setupReactContextRunnable =
                          new Runnable() {
                            @Override
                            public void run() {
                              try {
                                setupReactContext(reactApplicationContext);
                              } catch (Exception e) {
                                mDevSupportManager.handleException(e);
                              }
                            }
                          };
    
                      reactApplicationContext.runOnNativeModulesQueueThread(setupReactContextRunnable);
                      UiThreadUtil.runOnUiThread(maybeRecreateReactContextRunnable);
                    } catch (Exception e) {
                      mDevSupportManager.handleException(e);
                    }
                  }
                },
                "create_react_context");
        ReactMarker.logMarker(REACT_CONTEXT_THREAD_START);
        mCreateReactContextThread.start();
      }
    

    这个地方就是我们比较重要的创建ReactContext对象的逻辑。

       /** @return instance of {@link ReactContext} configured a {@link CatalystInstance} set */
      private ReactApplicationContext createReactContext(
          JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader) {
        Log.d(TAG, "FMsg:第六步:ReactInstanceManager.createReactContext " + Thread.currentThread().getName());
        Log.d(TAG, "FMsg:第六步:createReactContext() called with: jsExecutor = [" + jsExecutor + "], jsBundleLoader = [" + jsBundleLoader + "]");
        ReactMarker.logMarker(CREATE_REACT_CONTEXT_START, jsExecutor.getName());
        // 这个地方就进行了实例化reactContext
        // ReactApplicationContext extends ReactContext extends ContextWrapper
        // 构造函数传入的是Context。 eactApplicationContext是ReactContext的包装类。
        final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);
    
        // 这个就是NativeModuleCallExceptionHandler.异常捕获器
        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()
                    // 设置ReactNative的消息队列的配置数据
                .setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
                    // 通过JS执行器工厂实例化的JS线程执行器
                .setJSExecutor(jsExecutor)
                .setRegistry(nativeModuleRegistry)
                .setJSBundleLoader(jsBundleLoader)
                .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);
        }
    
        // 关联ReacContext与CatalystInstance实例化
        // 解析上面实例化的是三个线程封装对象
        reactContext.initializeWithInstance(catalystInstance);
    
        if (mJSIModulePackage != null) {
          // 这个默认是为null的。这个数据最初是在ReactNativeHost里面传入的
          catalystInstance.addJSIModules(
              mJSIModulePackage.getJSIModules(
                  reactContext, catalystInstance.getJavaScriptContextHolder()));
          // 这个地方没太看懂
          if (ReactFeatureFlags.useTurboModules) {
            catalystInstance.setTurboModuleManager(
                catalystInstance.getJSIModule(JSIModuleType.TurboModuleManager));
          }
        }
        if (mBridgeIdleDebugListener != null) {
          catalystInstance.addBridgeIdleDebugListener(mBridgeIdleDebugListener);
        }
        if (Systrace.isTracing(TRACE_TAG_REACT_APPS | TRACE_TAG_REACT_JS_VM_CALLS)) {
          catalystInstance.setGlobalVariable("__RCTProfileIsProfiling", "true");
        }
        ReactMarker.logMarker(ReactMarkerConstants.PRE_RUN_JS_BUNDLE_START);
        Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "runJSBundle");
        // 加载JSBundle的数据
        catalystInstance.runJSBundle();
        Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
    
        return reactContext;
      }
    

    这个是非常重要的方法,我们需要一点点来分析一下。

    1、首先他将Application的对象用ReactApplicationContext进行包装,生成ReactApplication对象。这个没什么好说的。简单的包装而已。

    2、创建JavaModule的注册表

    3、进行CatalystInstanceImpl实例化

    4、关联ReacContext与CatalystInstance实例化 解析上面实例化的是三个线程封装对象。这个地方。

    我们主要作用是让reactContext来持有catalystInstance对象 两个作用:1、获取这个实力上面传入ReactQueueConfigurationSpec实例,或者三个消息队列线程封装的对象 2、主要是通过催化器实例获取JSModule、NativeModule

    其次,ReacContext还有就是一些生命周期的管理

    实例化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.");
        Log.d(TAG, "FMsg:第七步:CatalystInstanceImpl() called with: reactQueueConfigurationSpec = [" + reactQueueConfigurationSpec + "], jsExecutor = [" + jsExecutor + "], nativeModuleRegistry = [" + nativeModuleRegistry + "], jsBundleLoader = [" + jsBundleLoader + "], nativeModuleCallExceptionHandler = [" + nativeModuleCallExceptionHandler + "]");
        Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createCatalystInstanceImpl");
    
        // 重点关注一下这一方法。这是一个Native方法。这样我们就调用到Native层
        mHybridData = initHybrid();
        // ReactNative的消息队列相关的实例化
        // TODO 这个地方要重点看一下
        // 这个主要是分别在对应的线程中创建消息任务队列的Handler(搬运工)
        // 当然还创建了两个线程(主线程不用创建)
        mReactQueueConfiguration =
            ReactQueueConfigurationImpl.create(
                reactQueueConfigurationSpec, new NativeExceptionHandler());
        mBridgeIdleListeners = new CopyOnWriteArrayList<>();
        // NativeModules注入器
        mNativeModuleRegistry = nativeModuleRegistry;
        mJSModuleRegistry = new JavaScriptModuleRegistry();
        // JSBundlerLoader
        mJSBundleLoader = jsBundleLoader;
        mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler;
        mNativeModulesQueueThread = mReactQueueConfiguration.getNativeModulesQueueThread();
        mTraceListener = new JSProfilerTraceListener(this);
        Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
    
        Log.d(TAG, "FMsg: 第七步:CatalystInstanceImpl() called Initializing React Xplat Bridge before initializeBridge");
        Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "initializeCxxBridge");
        Log.d(TAG, "FMsg:第七步:CatalystInstanceImpl() called with: initializeCxxBridge");
    
        // TODO 这个地方要重点看一下. 又一个非常重要的方法。
        // 初始化Java和Native之间的Bridge桥。这个是一个Native方法
        initializeBridge(
            //
            new BridgeCallback(this),
            // JSCore的JS引擎
            jsExecutor,
            // JS消息队列线程封装对象
            mReactQueueConfiguration.getJSQueueThread(),
                // Native消息队列线程封装对象
            mNativeModulesQueueThread,
            // 非C++的Modules就是JavaModule.也就是我们在Application里面封装的Modules
            // 这些NativeModules都会被封装成JavaModuleWrapper对象送给Native层
            mNativeModuleRegistry.getJavaModules(this),
            // 获取我们所有的Module中的C++的modules。这个是通过注解来标记那个NativeModule是C++
            // 但是我们翻了一下源码,没看到哪个NativeModule是C++
            mNativeModuleRegistry.getCxxModules());
        Log.d(ReactConstants.TAG, "第七步:实例化Initializing React Xplat Bridge after initializeBridge");
        Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
    
        mJavaScriptContextHolder = new JavaScriptContextHolder(getJavaScriptContext());
      }
    

    下面,我们看一下Native层的调用

    jni::local_ref<CatalystInstanceImpl::jhybriddata> CatalystInstanceImpl::initHybrid(
        jni::alias_ref<jclass>) {
       cout<<"===========FMsg:CatalystInstanceImpl initHybrid  called==============="<<endl;
      return makeCxxInstance();
    }
    
    void CatalystInstanceImpl::initializeBridge(
        jni::alias_ref<ReactCallback::javaobject> callback,
        // This executor is actually a factory holder.
        JavaScriptExecutorHolder* jseh,
        jni::alias_ref<JavaMessageQueueThread::javaobject> jsQueue,
        jni::alias_ref<JavaMessageQueueThread::javaobject> nativeModulesQueue,
        jni::alias_ref<jni::JCollection<JavaModuleWrapper::javaobject>::javaobject> javaModules,
        jni::alias_ref<jni::JCollection<ModuleHolder::javaobject>::javaobject> cxxModules) {
        LOG(INFO) <<"===========FMsg:CatalystInstanceImpl initializeBridge==============="<<endl;
        // .............省略部分代码
    
      moduleRegistry_ = std::make_shared<ModuleRegistry>(
        buildNativeModuleList(
           std::weak_ptr<Instance>(instance_),
           javaModules,
           cxxModules,
           moduleMessageQueue_));
    
      instance_->initializeBridge(
        std::make_unique<JInstanceCallback>(
        callback,
        moduleMessageQueue_),
        jseh->getExecutorFactory(),
        folly::make_unique<JMessageQueueThread>(jsQueue),
        moduleRegistry_);
    }
    

    至此,Java层的代码执行完毕。我们彻底就进入Native层的代码逻辑了。上面Jni代码中,调用的instance_->initializeBridge()。 这个逻辑层,我们要到Native层去查找逻辑实现了。

    void Instance::initializeBridge(
        std::unique_ptr<InstanceCallback> callback,
        std::shared_ptr<JSExecutorFactory> jsef,
        std::shared_ptr<MessageQueueThread> jsQueue,
        std::shared_ptr<ModuleRegistry> moduleRegistry) {
      LOG(INFO) <<"===========FMsg:Instance initializeBridge==============="<<endl;
      callback_ = std::move(callback);
      moduleRegistry_ = std::move(moduleRegistry);
      jsQueue->runOnQueueSync([this, &jsef, jsQueue]() mutable {
        nativeToJsBridge_ = folly::make_unique<NativeToJsBridge>(
            jsef.get(), moduleRegistry_, jsQueue, callback_);
    
        std::lock_guard<std::mutex> lock(m_syncMutex);
        m_syncReady = true;
        m_syncCV.notify_all();
      });
    
      CHECK(nativeToJsBridge_);
    }
    

    上线的代码中。催化器对象在启动的流程中的主要作用就完成了。主要就是将催化器初始化的一些Java、Native、JS层的一些通信对象准备好。

    我们在回过头去,看catalystInstance.runJSBundle()方法的调用。

      @Override
      public void runJSBundle() {
        Log.d(ReactConstants.TAG, "CatalystInstanceImpl.runJSBundle()");
        Log.d(TAG, "FMsg:第九步:runJSBundle() called");
        Assertions.assertCondition(!mJSBundleHasLoaded, "JS bundle was already loaded!");
        // incrementPendingJSCalls();
        mJSBundleLoader.loadScript(CatalystInstanceImpl.this);
    
        synchronized (mJSCallsPendingInitLock) {
    
          // Loading the bundle is queued on the JS thread, but may not have
          // run yet.  It's safe to set this here, though, since any work it
          // gates will be queued on the JS thread behind the load.
          mAcceptCalls = true;
    
          for (PendingJSCall function : mJSCallsPendingInit) {
            function.call(this);
          }
          mJSCallsPendingInit.clear();
          mJSBundleHasLoaded = true;
        }
    
        // This is registered after JS starts since it makes a JS call
        Systrace.registerListener(mTraceListener);
      }
    
      public static JSBundleLoader createFileLoader(
          final String fileName, final String assetUrl, final boolean loadSynchronously) {
        Log.d(TAG, "FMsg:第九步:createFileLoader() called with: fileName = [" + fileName + "], assetUrl = [" + assetUrl + "], loadSynchronously = [" + loadSynchronously + "]");
        return new JSBundleLoader() {
          @Override
          public String loadScript(JSBundleLoaderDelegate delegate) {
            delegate.loadScriptFromFile(fileName, assetUrl, loadSynchronously);
            return fileName;
          }
        };
      }
    
      @Override
      public void loadScriptFromFile(String fileName, String sourceURL, boolean loadSynchronously) {
        Log.d(TAG, "FMsg:第九步:loadScriptFromFile() called with: fileName = [" + fileName + "], sourceURL = [" + sourceURL + "], loadSynchronously = [" + loadSynchronously + "]");
        mSourceURL = sourceURL;
        jniLoadScriptFromFile(fileName, sourceURL, loadSynchronously);
      }
      
    

    这个jniLoadScriptFromFile也是一个Native的方法,我们可以看到他会调用到CatalystInstanceImpl.cpp的

    void CatalystInstanceImpl::jniLoadScriptFromFile(const std::string& fileName,
                                                     const std::string& sourceURL,
                                                     bool loadSynchronously) {
      LOG(INFO) <<"===========FMsg:CatalystInstanceImpl jniLoadScriptFromFile==============="<<endl;
      if (Instance::isIndexedRAMBundle(fileName.c_str())) {
        instance_->loadRAMBundleFromFile(fileName, sourceURL, loadSynchronously);
      } else {
        std::unique_ptr<const JSBigFileString> script;
        RecoverableError::runRethrowingAsRecoverable<std::system_error>(
          [&fileName, &script]() {
            script = JSBigFileString::fromPath(fileName);
          });
        instance_->loadScriptFromString(std::move(script), sourceURL, loadSynchronously);
      }
    }
    

    调用到Instancee.cpp的

    void Instance::loadScriptFromString(std::unique_ptr<const JSBigString> string,
                                        std::string sourceURL,
                                        bool loadSynchronously) {
      LOG(INFO) <<"===========FMsg:Instance loadScriptFromString==============="<<endl;
      SystraceSection s("Instance::loadScriptFromString", "sourceURL",
                        sourceURL);
      if (loadSynchronously) {
        loadApplicationSync(nullptr, std::move(string), std::move(sourceURL));
      } else {
        loadApplication(nullptr, std::move(string), std::move(sourceURL));
      }
    }
    
    
    void Instance::loadApplication(std::unique_ptr<RAMBundleRegistry> bundleRegistry,
                                   std::unique_ptr<const JSBigString> string,
                                   std::string sourceURL) {
      LOG(INFO) <<"===========FMsg:Instance loadApplication=========string======"<<endl;
      callback_->incrementPendingJSCalls();
      SystraceSection s("Instance::loadApplication", "sourceURL",
                        sourceURL);
      nativeToJsBridge_->loadApplication(std::move(bundleRegistry), std::move(string),
                                         std::move(sourceURL));
    }
    

    下面有调用到了

    void NativeToJsBridge::loadApplication(
        std::unique_ptr<RAMBundleRegistry> bundleRegistry,
        std::unique_ptr<const JSBigString> startupScript,
        std::string startupScriptSourceURL) {
       LOG(INFO) <<"===========FMsg:NativeToJsBridge loadApplication==============="<<endl;
      runOnExecutorQueue(
          [this,
           bundleRegistryWrap=folly::makeMoveWrapper(std::move(bundleRegistry)),
           startupScript=folly::makeMoveWrapper(std::move(startupScript)),
           startupScriptSourceURL=std::move(startupScriptSourceURL)]
            (JSExecutor* executor) mutable {
        auto bundleRegistry = bundleRegistryWrap.move();
        if (bundleRegistry) {
          executor->setBundleRegistry(std::move(bundleRegistry));
        }
         //executor从runOnExecutorQueue()返回的map中取得,与OnLoad中的JSCJavaScriptExecutorHolder对应,也与
         //Java中的JSCJavaScriptExecutor对应。它的实例在JSExecutor.cpp中实现。
        try {
          LOG(INFO) <<"===========FMsg:NativeToJsBridge executor  loadApplicationScript======" << startupScriptSourceURL << "。"<<endl;
          executor->loadApplicationScript(std::move(*startupScript),
                                          std::move(startupScriptSourceURL));
        } catch (...) {
          m_applicationScriptHasFailure = true;
          throw;
        }
      });
    }
    
    
    void NativeToJsBridge::runOnExecutorQueue(std::function<void(JSExecutor*)> task) {
      if (*m_destroyed) {
        return;
      }
    
      std::shared_ptr<bool> isDestroyed = m_destroyed;
      m_executorMessageQueueThread->runOnQueue([this, isDestroyed, task=std::move(task)] {
        if (*isDestroyed) {
          return;
        }
    
        // The executor is guaranteed to be valid for the duration of the task because:
        // 1. the executor is only destroyed after it is unregistered
        // 2. the executor is unregistered on this queue
        // 3. we just confirmed that the executor hasn't been unregistered above
        task(m_executor.get());
      });
    }
    

    下面,我们看到他调用了JSIExecutor的loadApplicationScript。下面我们来看一下这个方法的实现。

    void JSIExecutor::loadApplicationScript(
        std::unique_ptr<const JSBigString> script,
        std::string sourceURL) {
      SystraceSection s("JSIExecutor::loadApplicationScript");
      LOG(INFO) <<"===========FMsg:JSIExecutor loadApplicationScript===============sourceURL = " << sourceURL << "。" <<endl;
      // TODO: check for and use precompiled HBC
    
      runtime_->global().setProperty(
          *runtime_,
          "nativeModuleProxy",
          Object::createFromHostObject(
              *runtime_, std::make_shared<NativeModuleProxy>(*this)));
    
      runtime_->global().setProperty(
          *runtime_,
          "nativeFlushQueueImmediate",
          Function::createFromHostFunction(
              *runtime_,
              PropNameID::forAscii(*runtime_, "nativeFlushQueueImmediate"),
              1,
              [this](
                  jsi::Runtime &,
                  const jsi::Value &,
                  const jsi::Value *args,
                  size_t count) {
                if (count != 1) {
                  throw std::invalid_argument(
                      "nativeFlushQueueImmediate arg count must be 1");
                }
                // 应该是JSIExecutor⾥里里⾯面callNativeModules中的delegate_->callNativeModules
                LOG(INFO) <<"===========FMsg:JSIExecutor loadApplicationScript======callNativeModules======="<<endl;
                callNativeModules(args[0], false);
                return Value::undefined();
              }));
    
      runtime_->global().setProperty(
          *runtime_,
          "nativeCallSyncHook",
          Function::createFromHostFunction(
              *runtime_,
              PropNameID::forAscii(*runtime_, "nativeCallSyncHook"),
              1,
              [this](
                  jsi::Runtime &,
                  const jsi::Value &,
                  const jsi::Value *args,
                  size_t count) { return nativeCallSyncHook(args, count); }));
    
    #if DEBUG
      runtime_->global().setProperty(
          *runtime_,
          "globalEvalWithSourceUrl",
          Function::createFromHostFunction(
              *runtime_,
              PropNameID::forAscii(*runtime_, "globalEvalWithSourceUrl"),
              1,
              [this](
                  jsi::Runtime &,
                  const jsi::Value &,
                  const jsi::Value *args,
                  size_t count) { return globalEvalWithSourceUrl(args, count); }));
    #endif
    
      if (runtimeInstaller_) {
        runtimeInstaller_(*runtime_);
      }
    
      bool hasLogger(ReactMarker::logTaggedMarker);
      std::string scriptName = simpleBasename(sourceURL);
      if (hasLogger) {
        ReactMarker::logTaggedMarker(
            ReactMarker::RUN_JS_BUNDLE_START, scriptName.c_str());
      }
      //使用Webkit JSC去解释执行JS
      runtime_->evaluateJavaScript(
          std::make_unique<BigStringBuffer>(std::move(script)), sourceURL);
      flush();
      if (hasLogger) {
        ReactMarker::logMarker(ReactMarker::CREATE_REACT_CONTEXT_STOP);
        ReactMarker::logTaggedMarker(
            ReactMarker::RUN_JS_BUNDLE_STOP, scriptName.c_str());
      }
    }
    

    最后代码调用到evaluateJavaScript方法中。这个方法的实现JSCRuntime.cpp中。我们简简单看一下:

    jsi::Value JSCRuntime::evaluateJavaScript(
        const std::shared_ptr<const jsi::Buffer> &buffer,
        const std::string& sourceURL) {
      // LOG(INFO) <<"===========FMsg:JSCRuntime evaluateJavaScript===============sourceURL = " << sourceURL << "。" <<endl;
      std::string tmp(
          reinterpret_cast<const char*>(buffer->data()), buffer->size());
      JSStringRef sourceRef = JSStringCreateWithUTF8CString(tmp.c_str());
      JSStringRef sourceURLRef = nullptr;
      if (!sourceURL.empty()) {
        sourceURLRef = JSStringCreateWithUTF8CString(sourceURL.c_str());
      }
      JSValueRef exc = nullptr;
      JSValueRef res =
          JSEvaluateScript(ctx_, sourceRef, nullptr, sourceURLRef, 0, &exc);
      JSStringRelease(sourceRef);
      if (sourceURLRef) {
        JSStringRelease(sourceURLRef);
      }
      checkException(res, exc);
      return createValue(res);
    }
    

    从上面的代码中,我们我们开始加载JSBundle的逻辑已经执行完毕。但是这个时候其实ReactNative并没有启动起来。

    我们下面来看一下启动流程的最后一步:

    我们来回到ReactRootView的startReactApplication这个方法中的最后一步:

      private void attachToReactInstanceManager() {
        Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "attachToReactInstanceManager");
        Log.d(TAG, "FMsg:attachToReactInstanceManager() called");
        try {
          if (mIsAttachedToInstance) {
            return;
          }
    
          mIsAttachedToInstance = true;
            // ReactInstanceManager绑定到当前的RootView
          Assertions.assertNotNull(mReactInstanceManager).attachRootView(this);
          getViewTreeObserver().addOnGlobalLayoutListener(getCustomGlobalLayoutListener());
        } finally {
          Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
        }
      }
    

    方法很简单,我们来看attachRootView的实现

      public void attachRootView(ReactRoot reactRoot) {
        Log.d(TAG, "FMsg:attachRootView() called with: reactRoot = [" + reactRoot + "]");
        UiThreadUtil.assertOnUiThread();
        // ReactInstanceManager 是支持多 RootView 的.其实这个地方大家可以猜想,其实我们的ReactNative的页面,可以作为一个小的页面View
        // 附着到宿主Activity上。
        mAttachedReactRoots.add(reactRoot);
    
        // Reset reactRoot content as it's going to be populated by the application content from JS.
        clearReactRoot(reactRoot);
    
        // If react context is being created in the background, JS application will be started
        // automatically when creation completes, as reactRoot reactRoot is part of the attached
        // reactRoot reactRoot list.
        ReactContext currentContext = getCurrentReactContext();
        if (mCreateReactContextThread == null && currentContext != null) {
          // 最后,取出 ReactContext,让 ReactRootView 与 CatalystInstance 相关联:
          attachRootViewToInstance(reactRoot);
        }
      }
    
      private void attachRootViewToInstance(final ReactRoot reactRoot) {
        Log.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()");
        Log.d(TAG, "FMsg:第十步:attachRootViewToInstance() called with: reactRoot = [" + reactRoot + "]");
        Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "attachRootViewToInstance");
    
        // 首先通过 UIManagerHelper 拿到 UIManager:
        // UIManager 是什么呢?它有两个实现类:FabricUIManager、UIManagerModule
        // 我们来看后者,它的注释中说:这是一个原生模块,允许JS创建和更新原生视图。其实这个就是我们后来看RN的渲染流程中非常重要的类
        UIManager uiManager =
            UIManagerHelper.getUIManager(mCurrentReactContext, reactRoot.getUIManagerType());
    
        @Nullable Bundle initialProperties = reactRoot.getAppProperties();
    
        final int rootTag =
            uiManager.addRootView(
                reactRoot.getRootViewGroup(),
                initialProperties == null
                    ? new WritableNativeMap()
                    : Arguments.fromBundle(initialProperties),
                reactRoot.getInitialUITemplate());
        reactRoot.setRootViewTag(rootTag);
        if (reactRoot.getUIManagerType() == FABRIC) {
          // Fabric requires to call updateRootLayoutSpecs before starting JS Application,
          // this ensures the root will hace the correct pointScaleFactor.
          uiManager.updateRootLayoutSpecs(
              rootTag, reactRoot.getWidthMeasureSpec(), reactRoot.getHeightMeasureSpec());
          reactRoot.setShouldLogContentAppeared(true);
        } else {
          Log.d(TAG, "FMsg:第十步:attachRootViewToInstance() called with: reactRoot = [" + reactRoot + "]");
          // 这个方法就是我们真的去调用JS的相关代码,我们可以看看这个代码
          reactRoot.runApplication();
        }
        Systrace.beginAsyncSection(
            TRACE_TAG_REACT_JAVA_BRIDGE, "pre_rootView.onAttachedToReactInstance", rootTag);
        // 这个地方其实,我们有疑问:
        // 为什么使用UiThreadUtil.runOnUiThread。而不是
        //  mCurrentReactContext.runOnUiQueueThread();???
        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);
      }
    

    这个方法的最后一步,我们就可以看到reactRoot.runApplication() 这个方法很明显,就是运行起来JS的相关代码逻辑。

      @Override
      public void runApplication() {
        Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactRootView.runApplication");
        Log.d(TAG, "FMsg:第十一步:ReactRootView runApplication() called");
        try {
          if (mReactInstanceManager == null || !mIsAttachedToInstance) {
            return;
          }
    
          ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
          if (reactContext == null) {
            return;
          }
    
          CatalystInstance catalystInstance = reactContext.getCatalystInstance();
          String jsAppModuleName = getJSModuleName();
    
          if (mUseSurface) {
            // TODO call surface's runApplication
          } else {
            if (mWasMeasured) {
              updateRootLayoutSpecs(mWidthMeasureSpec, mHeightMeasureSpec);
            }
    
            WritableNativeMap appParams = new WritableNativeMap();
            appParams.putDouble("rootTag", getRootViewTag());
            @Nullable Bundle appProperties = getAppProperties();
            if (appProperties != null) {
              appParams.putMap("initialProps", Arguments.fromBundle(appProperties));
            }
    
            mShouldLogContentAppeared = true;
            Log.i(TAG, "FMsg: 第十步:==============runApplication: ==========================" + jsAppModuleName);
            Log.i(TAG, "FMsg: 第十步:==============runApplication: ==========================" + appParams);
            catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
          }
        } finally {
          Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
        }
      }
    

    这个方法也是比较简单的。通过ReactContext的实例,拿到催化器实例。然后通过催化器实例获取JSModule的runApplication

      @Override
      public <T extends JavaScriptModule> T getJSModule(Class<T> jsInterface) {
        // Log.d(TAG, "FMsg:getJSModule() called with: jsInterface = [" + jsInterface + "]");
        // mJSModuleRegistry注入器获取当前的注入器。至于怎么去获取的。我们可以再分析
        return mJSModuleRegistry.getJavaScriptModule(this, jsInterface);
      }
    

    可以看到,最终调用的是 catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams) , AppRegistry.class 是JS层暴露给Java层的接口方法。它的真正实现在 AppRegistry.js 里, AppRegistry.js 是运行所有 RN 应用的 JS 层入口,我们来看看它的实现:在 Libraries/ReactNative 中的 AppRegistry.js

      /**
       * Loads the JavaScript bundle and runs the app.
       *
       * See http://facebook.github.io/react-native/docs/appregistry.html#runapplication
       */
      runApplication(appKey: string, appParameters: any): void {
        const msg =
          'Running "' + appKey + '" with ' + JSON.stringify(appParameters);
        infoLog(msg);
        BugReporting.addSource(
          'AppRegistry.runApplication' + runCount++,
          () => msg,
        );
        invariant(
          runnables[appKey] && runnables[appKey].run,
          `"${appKey}" has not been registered. This can happen if:\n` +
            '* Metro (the local dev server) is run from the wrong folder. ' +
            'Check if Metro is running, stop it and restart it in the current project.\n' +
            "* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called.",
        );
    
        SceneTracker.setActiveScene({name: appKey});
        runnables[appKey].run(appParameters);
      },
    

    到这里就会去调用JS进行渲染,在通过 UIManagerModule 将JS组件转换成Android组件,最终显示在 ReactRootView 上。

    最后总结一下,就是先在应用终端启动并创建上下文对象,启动 JS Runtime ,进行布局,将JS端的代码通过C++层, UIManagerMoodule 转化成 Android 组件,再进行渲染,最后将渲染的View添加到 ReactRootView 上,最终呈现在用户面前。

    相关文章

      网友评论

          本文标题:ReactNative的启动流程精讲(基于ReactNative

          本文链接:https://www.haomeiwen.com/subject/owbkvhtx.html