加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 08:19:45 所属栏目:百科 来源:网络整理
导读:首先看JSBundleLoader, public static JSBundleLoader createFileLoader(final String fileName) { return new JSBundleLoader() { @Override public void loadScript(CatalystInstanceImpl instance) { instance.loadScriptFromFile(fileName,fileName); }

首先看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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读