React Native启动流程集合安卓源码分析

《React Native启动流程集合安卓源码分析》

首先看JSBundleLoader,

  public static JSBundleLoader createFileLoader(final String fileName) {
    return new JSBundleLoader() {
      @Override
      public void loadScript(CatalystInstanceImpl instance) {
        instance.loadScriptFromFile(fileName, fileName);
      }

      @Override
      public String getSourceUrl() {
        return fileName;
      }
    };
  }

JSBundlerLoader本身是用来加载JS Bundle的,本质上它还是调用CatalyInstanceImpl总的native方法走到C++层

  /* package */ native void loadScriptFromAssets(AssetManager assetManager, String assetURL);
  /* package */ native void loadScriptFromFile(String fileName, String sourceURL);
  /* package */ native void loadScriptFromOptimizedBundle(String path, String sourceURL, int flags);

在XReactInstanceManagerImpl执行createReactContext的时候,会调用到CatalyInstanceImpl的runJSBundle

而runJSBundler本质还是调用 mJSBundleLoader.loadScript(CatalystInstanceImpl.this);去加载JS

就这样传递到C++层,结合JavaScriptCore对JS进行解释执行了

对于开发模式我们看到在XReactInstanceManagerImpl中会执行到onJSBundleLoadedFromServer,

先从服务端获取JSBundle

注意:实际加载请求等应该发生于C++端

以上参考自:http://www.jianshu.com/p/17d6f6c57a5c

现在我想知道ReactNativeHOST是如何被利用的,如何通过这家伙拿到Bundle的路径,我们又如何自定义Bundle的路径

要回答这个问题,首先先补课:

  <application
        android:allowBackup=”true”
        android:name=”.MainApplication”
        android:icon=”@mipmap/ic_launcher”
        android:label=”@string/app_name”
        android:supportsRtl=”true”

我们自定义了一个MainApplication,

  Application application = getApplication();
                if(application instanceof MainApplication){
                    Toast.makeText(application,”是MainApplication的实例”,Toast.LENGTH_LONG).show();
                }else {
                    Toast.makeText(application,”不是MainApplication的实例”,Toast.LENGTH_LONG).show();
                }

结果显示是MainAppction的实例,所有我们首先明确这一点

我们现在先看看使用RN的第一张写法 

public class MainActivity extends ReactActivity {
 
    @Override
    protected String getMainComponentName() {
        ..
    }
 
    @Override
    protected boolean getUseDeveloperSupport() {
        return BuildConfig.DEBUG;
    }
 
 //   @Override
 //   protected List<ReactPackage> getPackages() {
 //      return Arrays.<ReactPackage>asList(
 //               new MainReactPackage()
 //       );
    }
}

在里面我们会获取到一个ReactNativeHost

  protected ReactNativeHost getReactNativeHost() {
    return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost();
  }

所有采用这种方式我们要把MainApplication实现ReactApplication,否则会被强制转换异常的,看图

《React Native启动流程集合安卓源码分析》

我们注意到我们是从当前Activity的Application是获取的

所有我们在MainApplication实现ReactApplication接口,那么通过当前Activity就能拿到MainApplication,从而

调用到接口中的getReactNativeHost了

public class MainApplication extends  Application implements ReactApplication {

    private Application context;

    @Override
    public ReactNativeHost getReactNativeHost() {
        context = this;
        ReactNativeHost host = null;
        if (host==null){
            host = new ReactNativeHost(context) {
                @Override
                protected boolean getUseDeveloperSupport() {
                    return false;
                }

                @Override
                protected List<ReactPackage> getPackages() {
                    return Arrays.<ReactPackage>asList(
                            new MainReactPackage(),
                            new IntentReactPackage()
                    );
                }
            };
        }

        return host;
    }

}

经过一系列的调用会执行到

  protected ReactInstanceManager createReactInstanceManager() {
    ReactInstanceManager.Builder builder = ReactInstanceManager.builder()
      .setApplication(mApplication)
      .setJSMainModuleName(getJSMainModuleName())
      .setUseDeveloperSupport(getUseDeveloperSupport())
      .setRedBoxHandler(getRedBoxHandler())
      .setUIImplementationProvider(getUIImplementationProvider())
      .setInitialLifecycleState(LifecycleState.BEFORE_CREATE);

    for (ReactPackage reactPackage : getPackages()) {
      builder.addPackage(reactPackage);
    }

    String jsBundleFile = getJSBundleFile();
    if (jsBundleFile != null) {
      builder.setJSBundleFile(jsBundleFile);
    } else {
      builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName()));
    }
    return builder.build();
  }

注意红色的两句,就是我们利用ReactNativeHost里指定的路径的代码,

第二种写法

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mReactRootView = new ReactRootView(this);
    mReactInstanceManager = ReactInstanceManager.builder()
            .setApplication(getApplication())
            .setBundleAssetName("index.android.bundle")
            .setJSMainModuleName("index.android")
            .addPackage(new MainReactPackage())
            .setUseDeveloperSupport(BuildConfig.DEBUG)
            .setInitialLifecycleState(LifecycleState.RESUMED)
            .build();
    mReactRootView.startReactApplication(mReactInstanceManager, "HelloWorld", null);

    setContentView(mReactRootView);
}

这个是我们自己new ReactInstanceManager的,我们传递的BudlerAssetName会被组成Bundle的路径

public Builder setBundleAssetName(String bundleAssetName) {
  mJSBundleAssetUrl = (bundleAssetName == null ? null : "assets://" + bundleAssetName);
  mJSBundleLoader = null;
  return this;
}

这中写法我猜测可能没有利用到ReactNativeHOST吧

本文另外参考了:http://www.cnblogs.com/zhang740/p/5978323.html

http://blog.csdn.net/ssksuke/article/details/52403754?locationNum=6

    原文作者:java集合源码分析
    原文地址: https://blog.csdn.net/rnzuozuo/article/details/53257666
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞