您的位置:首页 > Web前端 > React

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

2016-11-21 11:36 567 查看


首先看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,否则会被强制转换异常的,看图



我们注意到我们是从当前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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: