欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

簡析React Native startReactApplication 方法

 更新時間:2021年09月07日 17:22:55   作者:Yutoti_三石  
這篇文章主要介紹了React Native startReactApplication 方法簡析,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

React Native 啟動流程簡析 這篇文章里,我們梳理了 RN 的啟動流程,最后的 startReactApplication 由于相對復(fù)雜且涉及到最終執(zhí)行前端 js 的流程,我們單獨(dú)將其提取出來,獨(dú)立成文加以分析。

首先來看 startReactApplication 的調(diào)用之處:

mReactRootView.startReactApplication(
    getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions);

可以看到是在 rootView 上調(diào)用 startReactApplication,入?yún)?instanceManager、appKey、mLaunchOptions。

順著 startReactApplication 扒出其調(diào)用鏈:

mReactInstanceManager.createReactContextInBackground() -> recreateReactContextInBackgroundInner() -> recreateReactContextInBackgroundFromBundleLoader() -> recreateReactContextInBackground() -> runCreateReactContextOnNewThread()

recreateReactContextInBackgroundReactInstanceManager 中的方法,做了兩件事:

1.創(chuàng)建 ReactContextInitParams 實(shí)例 initParams,如下,其入?yún)?jsExecutorFactory 為創(chuàng)建 ReactInstanceManager 時傳入。

final ReactContextInitParams initParams =
    new ReactContextInitParams(jsExecutorFactory, jsBundleLoader);

2.調(diào)用 runCreateReactContextOnNewThread

runCreateReactContextOnNewThreadReactInstanceManager 中的方法,主要做了兩件事:

  1. 創(chuàng)建一個新的線程,并在新線程中通過 createReactContext 創(chuàng)建 ReactContext 上下文;
  2. 通過 setupReactContext 來設(shè)置上下文環(huán)境,并最終調(diào)用到 AppRegistry.js 啟動App。

createReactContext

先看其調(diào)用的地方:

final ReactApplicationContext reactApplicationContext =
    createReactContext(
        initParams.getJsExecutorFactory().create(),
        initParams.getJsBundleLoader());

其兩個入?yún)⒎謩e為 JsExecutorFactory 創(chuàng)建的 JavaScriptExecutor 實(shí)例,和 JsBundleLoader 實(shí)例。

JavaScriptExecutor

startReactApplication 第一個入?yún)?getReactNativeHost().getReactInstanceManager() 獲取 ReactInstanceManager 實(shí)例。ReactInstanceManager 實(shí)例在 RN 應(yīng)用中只有一個,先前在創(chuàng)建 MainActivity 時已創(chuàng)建。

回顧 React Native 啟動流程簡析,在創(chuàng)建過程中實(shí)際上是調(diào)用下面的方法:

ReactInstanceManager reactInstanceManager = builder.build()

builderReactInstanceManagerBuilder,我們來到該類的 build 方法,發(fā)現(xiàn)其最終是執(zhí)行 return new ReactInstanceManager(...),在構(gòu)造參數(shù)中第 4 個參數(shù)即為:getDefaultJSExecutorFactory,來到其定義處:

 private JavaScriptExecutorFactory getDefaultJSExecutorFactory(
      String appName, String deviceName, Context applicationContext) {
    try {
      // If JSC is included, use it as normal
      initializeSoLoaderIfNecessary(applicationContext);
      SoLoader.loadLibrary("jscexecutor");
      return new JSCExecutorFactory(appName, deviceName);
    } catch (UnsatisfiedLinkError jscE) { /* ... */ }
}

也就是說在創(chuàng)建 ReactInstanceManagerBuilder 時我們就創(chuàng)建了 JSCExecutorFactory,并在隨后調(diào)用其 create 方法創(chuàng)建 JSCExecutor 。JSCExecutorFactory 實(shí)現(xiàn)了 JavaScriptExecutorFactory 接口,其 create 方法如下,返回了 JSCExecutor 實(shí)例:

 @Override
  public JavaScriptExecutor create() throws Exception {
    WritableNativeMap jscConfig = new WritableNativeMap();
    jscConfig.putString("OwnerIdentity", "ReactNative");
    jscConfig.putString("AppIdentity", mAppName);
    jscConfig.putString("DeviceIdentity", mDeviceName);
    return new JSCExecutor(jscConfig);
  }

再往下看 JSCExecutor 的定義,其繼承自 JavaScriptExecutor 類:

@DoNotStrip
/* package */ class JSCExecutor extends JavaScriptExecutor {
  static {
    SoLoader.loadLibrary("jscexecutor");
  }
  /* package */ JSCExecutor(ReadableNativeMap jscConfig) {
    super(initHybrid(jscConfig));
  }
  @Override
  public String getName() {
    return "JSCExecutor";
  }
  private static native HybridData initHybrid(ReadableNativeMap jscConfig);
}

于是就很清楚了,createReactContext 第一個參數(shù)為 JSCExecutor 實(shí)例,是通過 SoLoader 加載的 C++ 模塊。

JsBundleLoader

同樣的,在 return new ReactInstanceManager(...),其構(gòu)造參數(shù)中第 5 個參數(shù)為:JSBundleLoader.createAssetLoader(mApplication, mJSBundleAssetUrl, false)

來到其定義之處,發(fā)現(xiàn)其返回了 JSBundleLoader 實(shí)例,并重寫了其 loadScript 方法。

public static JSBundleLoader createAssetLoader(
    final Context context, final String assetUrl, final boolean loadSynchronously) {
  return new JSBundleLoader() {
    @Override
    public String loadScript(JSBundleLoaderDelegate delegate) {
      delegate.loadScriptFromAssets(context.getAssets(), assetUrl, loadSynchronously);
      return assetUrl;
    }
  };
}

在創(chuàng)建完 JSCExecutor 實(shí)例和 JSBundleLoader 實(shí)例后,正式進(jìn)入到 createReactContext 方法。

createReactContext

private ReactApplicationContext createReactContext(
  final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);

  CatalystInstanceImpl.Builder catalystInstanceBuilder = /* ... */

  try {
    catalystInstance = catalystInstanceBuilder.build();
  } finally { /* ... */ }

  reactContext.initializeWithInstance(catalystInstance);

  TurboModuleManager turboModuleManager =
    new TurboModuleManager( /* ... */ )

  catalystInstance.setTurboModuleManager(turboModuleManager);

  if (mJSIModulePackage != null) {
    catalystInstance.addJSIModules( /* ... */ );
  }

  catalystInstance.runJSBundle();
  return reactContext;

在這里面,首先創(chuàng)建了 reactContext,并通過 catalystInstanceBuilder 創(chuàng)建了 catalystInstance。接著通過 initializeWithInstance 方法將 reactContextcatalystInstance 關(guān)聯(lián)起來,并進(jìn)行了一系列的為 catalystInstance 初始化的工作。最后進(jìn)入到方法 catalystInstance.runJSBundle() 中。

initializeWithInstance

通過調(diào)用 getUIQueueThread、getNativeModulesQueueThread、getJSQueueThread創(chuàng)建了3個線程隊列,分別是 UI線程、NativeModules 線程,和 JS 線程。

runJSBundle

public void runJSBundle() {
  mJSBundleLoader.loadScript(CatalystInstanceImpl.this);
  synchronized (mJSCallsPendingInitLock) {
    mAcceptCalls = true;
    for (PendingJSCall function : mJSCallsPendingInit) {
      function.call(this);
    }
    mJSCallsPendingInit.clear();
    mJSBundleHasLoaded = true;
  }
  Systrace.registerListener(mTraceListener);
}

通過先前返回的 mJSBundleLoader 執(zhí)行其 loadScript 方法:

public String loadScript(JSBundleLoaderDelegate delegate) {
  delegate.loadScriptFromAssets(context.getAssets(), assetUrl, loadSynchronously);
  return assetUrl;
}

loadScriptFromAssets 方法在 CatalystInstanceImpl 中:

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

這里的 assetURL 是在 createAssetLoader 創(chuàng)建 mJSBundleLoader 時傳入,其賦值時機(jī)是在 reactInstanceManagerBuilder 實(shí)例中,由 reactNativeHost 實(shí)例的 createReactInstanceManager 方法。若 開發(fā)者在 MainApplication.java 中通過重寫 getJSBundleFile 方法自定義了 assetURL 則使用該 url,否則使用系統(tǒng)默認(rèn),如:file://sdcard/myapp_cache/index.android.bundle。

jniLoadScriptFromAssets 方法為 C++ 側(cè)定義的方法,用于讀取 js 文件。為什么 Java 代碼中可以直接調(diào)用 C++ 方法,這里還要打個問號,后續(xù)在分析 Java 與 C++ 通信及 Java 與 JS 通信時闡釋。

通過 createReactContext 創(chuàng)建了 reactContext,創(chuàng)建了 catalystInstance 實(shí)例,并將上述兩者關(guān)聯(lián),接著通過 catalystInstance 讀入 js 文件。接下來就進(jìn)入到 setupReactContext 的環(huán)節(jié)。

setupReactContext

private void setupReactContext(final ReactApplicationContext reactContext) {
    synchronized (mAttachedReactRoots) {
      catalystInstance.initialize();
      for (ReactRoot reactRoot : mAttachedReactRoots) {
        if (reactRoot.getState().compareAndSet(ReactRoot.STATE_STOPPED, ReactRoot.STATE_STARTED)) {
          attachRootViewToInstance(reactRoot);
        }
      }
    }
    UiThreadUtil.runOnUiThread(
      public void run() {
        listener.onReactContextInitialized(reactContext);
      }
    )
    reactContext.runOnJSQueueThread(
      public void run() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
      }
    )
    reactContext.runOnNativeModulesQueueThread(
      public void run() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
      }
    )
}

這里面做的事情如下:

  • catalystInstance.initialize(): 所有原生模塊的初始化
  • attachRootViewToInstance(reactRoot): 繪制所有的 RootView 并添加到相應(yīng)實(shí)例并設(shè)置相應(yīng)的監(jiān)聽事件
  • 創(chuàng)建 UI 模塊、JS 模塊和原生模塊線程,并設(shè)置 JS 模塊和原生模塊所在線程的優(yōu)先級

總結(jié)本文

從 createReactContext 和 setupReactContext 兩個方法的源碼出發(fā),分析了 RN startReactApplication 方法的執(zhí)行過程,其中:

createReactContext 的主要作用是:創(chuàng)建 reactContext、創(chuàng)建 catalystInstance 實(shí)例,并將上述兩者關(guān)聯(lián),接著通過 catalystInstance 讀入 js 文件。

setupReactContext的主要作用是:初始化所有原生模塊,繪制所有 rootview,創(chuàng)建 UI 模塊、JS 模塊和原生模塊線程,并設(shè)置優(yōu)先級。

到此這篇關(guān)于React Native startReactApplication 方法簡析的文章就介紹到這了,更多相關(guān)React Native startReactApplication內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React?Hooks使用startTransition與useTransition教程示例

    React?Hooks使用startTransition與useTransition教程示例

    這篇文章主要為大家介紹了React?Hooks使用startTransition與useTransition教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • React教程之封裝一個Portal可復(fù)用組件的方法

    React教程之封裝一個Portal可復(fù)用組件的方法

    react的核心之一是組件,下面這篇文章主要給大家介紹了關(guān)于React教程之封裝一個Portal可復(fù)用組件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • react 項目中引入圖片的幾種方式

    react 項目中引入圖片的幾種方式

    本文主要介紹了react 項目中引入圖片,本文詳細(xì)的介紹了幾種方法,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • React獲取Java后臺文件流并下載Excel文件流程解析

    React獲取Java后臺文件流并下載Excel文件流程解析

    這篇文章主要介紹了React獲取Java后臺文件流下載Excel文件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • 深入學(xué)習(xí)TypeScript 、React、 Redux和Ant-Design的最佳實(shí)踐

    深入學(xué)習(xí)TypeScript 、React、 Redux和Ant-Design的最佳實(shí)踐

    這篇文章主要介紹了深入學(xué)習(xí)TypeScript 、React、 Redux和Ant-Design的最佳實(shí)踐,TypeScript 增加了代碼的可讀性和可維護(hù)性,擁有活躍的社區(qū),,需要的朋友可以參考下
    2019-06-06
  • react hooks實(shí)現(xiàn)原理解析

    react hooks實(shí)現(xiàn)原理解析

    這篇文章主要介紹了react hooks實(shí)現(xiàn)原理,文中給大家介紹了useState dispatch 函數(shù)如何與其使用的 Function Component 進(jìn)行綁定,節(jié)后實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • 基于React?Hooks的小型狀態(tài)管理詳解

    基于React?Hooks的小型狀態(tài)管理詳解

    本文主要介紹一種基于?React?Hooks?的狀態(tài)共享方案,介紹其實(shí)現(xiàn),并總結(jié)一下使用感受,目的是在狀態(tài)管理方面提供多一種選擇方式。感興趣的小伙伴可以了解一下
    2021-12-12
  • 淺談react-native熱更新react-native-pushy集成遇到的問題

    淺談react-native熱更新react-native-pushy集成遇到的問題

    下面小編就為大家?guī)硪黄獪\談react-native熱更新react-native-pushy集成遇到的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • 在react項目中使用antd的form組件,動態(tài)設(shè)置input框的值

    在react項目中使用antd的form組件,動態(tài)設(shè)置input框的值

    這篇文章主要介紹了在react項目中使用antd的form組件,動態(tài)設(shè)置input框的值,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • React中的useState和useEffect詳細(xì)解析

    React中的useState和useEffect詳細(xì)解析

    useState和useEffect是React的兩個重要Hook,用于組件狀態(tài)管理和處理副作用,useState允許添加狀態(tài)變量,控制組件渲染,而useEffect用于執(zhí)行渲染后的副作用操作,本文給大家介紹React中的useState和useEffect詳細(xì)解析,感興趣的朋友跟隨小編一起看看吧
    2024-10-10

最新評論