最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

簡析React Native startReactApplication 方法

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

React Native 啟動(dòng)流程簡析 這篇文章里,我們梳理了 RN 的啟動(dòng)流程,最后的 startReactApplication 由于相對(duì)復(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 時(shí)傳入。

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

2.調(diào)用 runCreateReactContextOnNewThread

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

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

createReactContext

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

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

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

JavaScriptExecutor

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

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

ReactInstanceManager reactInstanceManager = builder.build()

builderReactInstanceManagerBuilder,我們來到該類的 build 方法,發(fā)現(xiàn)其最終是執(zhí)行 return new ReactInstanceManager(...),在構(gòu)造參數(shù)中第 4 個(gè)參數(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 時(shí)我們就創(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 第一個(gè)參數(shù)為 JSCExecutor 實(shí)例,是通過 SoLoader 加載的 C++ 模塊。

JsBundleLoader

同樣的,在 return new ReactInstanceManager(...),其構(gòu)造參數(shù)中第 5 個(gè)參數(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)用 getUIQueueThreadgetNativeModulesQueueThread、getJSQueueThread創(chuàng)建了3個(gè)線程隊(duì)列,分別是 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 時(shí)傳入,其賦值時(shí)機(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++ 方法,這里還要打個(gè)問號(hào),后續(xù)在分析 Java 與 C++ 通信及 Java 與 JS 通信時(shí)闡釋。

通過 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)先級(jí)

總結(jié)本文

從 createReactContext 和 setupReactContext 兩個(gè)方法的源碼出發(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)先級(jí)。

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

相關(guān)文章

  • React獲取input值并提交的2種方法實(shí)例

    React獲取input值并提交的2種方法實(shí)例

    這篇文章主要給大家介紹了關(guān)于React獲取input值并提交的2種方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 一文詳解ReactNative狀態(tài)管理rematch使用

    一文詳解ReactNative狀態(tài)管理rematch使用

    這篇文章主要為大家介紹了ReactNative狀態(tài)管理rematch使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • React實(shí)現(xiàn)生成和導(dǎo)出Word文檔的方法詳解

    React實(shí)現(xiàn)生成和導(dǎo)出Word文檔的方法詳解

    React是一個(gè)流行的JavaScript庫,用于構(gòu)建現(xiàn)代前端應(yīng)用程序,本文將深入探討如何在React中生成和導(dǎo)出Word文檔,感興趣的小伙伴可以學(xué)習(xí)一下
    2023-09-09
  • React RenderProps模式運(yùn)用過程淺析

    React RenderProps模式運(yùn)用過程淺析

    render props是指一種在 React 組件之間使用一個(gè)值為函數(shù)的 prop 共享代碼的技術(shù)。簡單來說,給一個(gè)組件傳入一個(gè)prop,這個(gè)props是一個(gè)函數(shù),函數(shù)的作用是用來告訴這個(gè)組件需要渲染什么內(nèi)容,那么這個(gè)prop就成為render prop
    2023-03-03
  • React項(xiàng)目中動(dòng)態(tài)插入HTML內(nèi)容的實(shí)現(xiàn)

    React項(xiàng)目中動(dòng)態(tài)插入HTML內(nèi)容的實(shí)現(xiàn)

    本文主要介紹了React項(xiàng)目中動(dòng)態(tài)插入HTML內(nèi)容的實(shí)現(xiàn),通過使用React的dangerouslySetInnerHTML屬性,我們可以將HTML內(nèi)容插入到組件中,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • React結(jié)合Drag?API實(shí)現(xiàn)拖拽示例詳解

    React結(jié)合Drag?API實(shí)現(xiàn)拖拽示例詳解

    這篇文章主要為大家介紹了React結(jié)合Drag?API實(shí)現(xiàn)拖拽示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • React手寫簽名組件react-signature實(shí)現(xiàn)簽字demo

    React手寫簽名組件react-signature實(shí)現(xiàn)簽字demo

    這篇文章主要為大家介紹了React手寫簽名組件react-signature實(shí)現(xiàn)簽字demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • React UI組件庫ant-design的介紹與使用

    React UI組件庫ant-design的介紹與使用

    Ant Design是阿里螞蟻金服團(tuán)隊(duì)基于React開發(fā)的ui組件,主要用于中后臺(tái)系統(tǒng)的使用,這篇文章主要介紹了React UI組件庫ant-design的介紹與使用,需要的朋友可以參考下
    2023-12-12
  • React配置代理方式(proxy)

    React配置代理方式(proxy)

    這篇文章主要介紹了React配置代理方式(proxy),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • React useReducer終極使用教程

    React useReducer終極使用教程

    useReducer是在react V16.8推出的鉤子函數(shù),從用法層面來說是可以代替useState。相信前期使用過 React 的前端同學(xué),大都會(huì)經(jīng)歷從class語法向hooks用法的轉(zhuǎn)變,react的hooks編程給我們帶來了絲滑的函數(shù)式編程體驗(yàn)
    2022-10-10

最新評(píng)論

福海县| 桦南县| 株洲市| 辽中县| 华安县| 铜鼓县| 定远县| 上栗县| 武胜县| 岑巩县| 石渠县| 五常市| 奉贤区| 临潭县| 奇台县| 丹棱县| 石渠县| 睢宁县| 五峰| 新和县| 武鸣县| 乐至县| 当阳市| 化德县| 南部县| 锡林郭勒盟| 攀枝花市| 调兵山市| 仲巴县| 菏泽市| 科尔| 化州市| 当雄县| 新巴尔虎左旗| 珲春市| 理塘县| 新竹县| 鄂尔多斯市| 靖西县| 霍城县| 紫云|