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

簡(jiǎn)析React Native startReactApplication 方法

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

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

首先來(lái)看 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è)新的線程,并在新線程中通過(guò) createReactContext 創(chuàng)建 ReactContext 上下文;
  2. 通過(guò) setupReactContext 來(lái)設(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)流程簡(jiǎn)析,在創(chuàng)建過(guò)程中實(shí)際上是調(diào)用下面的方法:

ReactInstanceManager reactInstanceManager = builder.build()

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

 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) { /* ... */ }
}

也就是說(shuō)在創(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í)例,是通過(guò) SoLoader 加載的 C++ 模塊。

JsBundleLoader

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

來(lái)到其定義之處,發(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,并通過(guò) catalystInstanceBuilder 創(chuàng)建了 catalystInstance。接著通過(guò) initializeWithInstance 方法將 reactContextcatalystInstance 關(guān)聯(lián)起來(lái),并進(jìn)行了一系列的為 catalystInstance 初始化的工作。最后進(jìn)入到方法 catalystInstance.runJSBundle() 中。

initializeWithInstance

通過(guò)調(diào)用 getUIQueueThread、getNativeModulesQueueThreadgetJSQueueThread創(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);
}

通過(guò)先前返回的 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 中通過(guò)重寫 getJSBundleFile 方法自定義了 assetURL 則使用該 url,否則使用系統(tǒng)默認(rèn),如:file://sdcard/myapp_cache/index.android.bundle。

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

通過(guò) createReactContext 創(chuàng)建了 reactContext,創(chuàng)建了 catalystInstance 實(shí)例,并將上述兩者關(guān)聯(lián),接著通過(guò) catalystInstance 讀入 js 文件。接下來(lái)就進(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í)行過(guò)程,其中:

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

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

到此這篇關(guān)于React Native startReactApplication 方法簡(jiǎn)析的文章就介紹到這了,更多相關(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種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(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庫(kù),用于構(gòu)建現(xiàn)代前端應(yīng)用程序,本文將深入探討如何在React中生成和導(dǎo)出Word文檔,感興趣的小伙伴可以學(xué)習(xí)一下
    2023-09-09
  • React RenderProps模式運(yùn)用過(guò)程淺析

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

    render props是指一種在 React 組件之間使用一個(gè)值為函數(shù)的 prop 共享代碼的技術(shù)。簡(jiǎn)單來(lái)說(shuō),給一個(gè)組件傳入一個(gè)prop,這個(gè)props是一個(gè)函數(shù),函數(shù)的作用是用來(lái)告訴這個(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),通過(guò)使用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組件庫(kù)ant-design的介紹與使用

    React UI組件庫(kù)ant-design的介紹與使用

    Ant Design是阿里螞蟻金服團(tuán)隊(duì)基于React開發(fā)的ui組件,主要用于中后臺(tái)系統(tǒng)的使用,這篇文章主要介紹了React UI組件庫(kù)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ù),從用法層面來(lái)說(shuō)是可以代替useState。相信前期使用過(guò) React 的前端同學(xué),大都會(huì)經(jīng)歷從class語(yǔ)法向hooks用法的轉(zhuǎn)變,react的hooks編程給我們帶來(lái)了絲滑的函數(shù)式編程體驗(yàn)
    2022-10-10

最新評(píng)論

呼图壁县| 营山县| 张掖市| 庆安县| 昌乐县| 松潘县| 会泽县| 安陆市| 博客| 祁门县| 江都市| 辽宁省| 辛集市| 称多县| 子长县| 祁阳县| 长沙县| 横峰县| 南昌县| 武乡县| 云南省| 固镇县| 迁安市| 沙坪坝区| 惠安县| 密山市| 大方县| 南漳县| 玛纳斯县| 朝阳县| 望城县| 泽州县| 郓城县| 阜阳市| 习水县| 榆社县| 泸水县| 盐山县| 汕尾市| 元氏县| 莱芜市|