当RN项目创建完成后,打开android目录,可以看到在原生代码中会生成 MainActivity和 MainApplication 两个Java类。很明显没,MainActivity 即为原生层应用程序的入口文件。MainApplication作为整体应用程序的初始化入口文件。我们先来看 MainActivity.java 文件:
public class MainActivity extends ReactActivity {
/**
* 返回在rn index.js 注册的名称,
* 即 AppRegistry.registerComponent()传入的名称,用来渲染组件。
*/
@Override
protected String getMainComponentName() {
return “example”;
}
}
可以看到MainActivity继承 ReactActivity 并实现 getMainComponentName 方法,返回与 AppRegistry.registerComponent 的 appKey 相同名称即可。继续来看 MainApplication.java 文件:
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List getPackages() {
return Arrays.asList(
new MainReactPackage()
);
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
// 加载C++层渲染代码
SoLoader.init(this,false);
}
}
MainApplication 中主要完成了三件事:
了解完两个文件,我们先从 MainActivity 开始分析。
MainActivity
MainActivity 继承 ReactActivity 类,重写了getMainComponentName 方法,并且方法的返回值需要和我们在JS端的值保持一致。
通过上面我们分析的 AppRegistry.js 中的 runApplication 方法发现:如果 getMainComponentName 中返回的名称与 RN 层 AppRegistry.registerComponent 注册名称不一致,会出现 Application XXX appKey has not been registered 异常。跟进 ReactActivity 类,看下核心代码:
package com.facebook.react;
/**
private final ReactActivityDelegate mDelegate;
protected ReactActivity() {
mDelegate = createReactActivityDelegate();
}
/**
/**
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDelegate.onCreate(savedInstanceState);
}
… 中间省略生命周期、返回事件、权限申请函数
/**
/**
/**
/**
private final @Nullable Activity mActivity;
private final @Nullable FragmentActivity mFragmentActivity;
private final @Nullable String mMainComponentName;
private @Nullable ReactRootView mReactRootView;
private @Nullable DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;
…
public ReactActivityDelegate(Activity activity, @Nullable String mainComponentName) {
mActivity = activity;
mMainComponentName = mainComponentName;
mFragmentActivity = null;
}
public ReactActivityDelegate(
FragmentActivity fragmentActivity,
@Nullable String mainComponentName) {
mFragmentActivity = fragmentActivity;
mMainComponentName = mainComponentName;
mActivity = null;
}
protected @Nullable Bundle getLaunchOptions() {
return null;
}
protected ReactRootView createRootView() {
return new ReactRootView(getContext());
}
/**
public ReactInstanceManager getReactInstanceManager() {
return getReactNativeHost().getReactInstanceManager();
}
protected void onCreate(Bundle savedInstanceState) {
if (mMainComponentName != null) {
loadApp(mMainComponentName);
}
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
}
protected void loadApp(String appKey) {
if (mReactRootView != null) {
throw new IllegalStateException(“Cannot loadApp while app is already running.”);
}
mReactRootView = createRootView();
mReactRootView.startReactApplication(
getReactNativeHost().getReactInstanceManager(),
appKey,
getLaunchOptions());
getPlainActivity().setContentView(mReactRootView);
}
… 中间省略生命周期、返回事件、权限请求的方法
private Context getContext() {
if (mActivity != null) {
return mActivity;
}
return Assertions.assertNotNull(mFragmentActivity);
}
private Activity getPlainActivity() {
return ((Activity) getContext());
}
}
ReactActivityDelegate 类中主要完成这几件事:
1. 创建 RootView
2. 调用 RootView 实例的 startReactApplication 方法,将 ReactInstanceManager 实例、appKey、启动时初始化参数作为参数传递过去
3. 将 ReactRootView 设置为 MainActivity 布局视图
从 ReactActivityDelegate 方法中,我们了解到很多方法都交给了 ReactInstanceManager 实例去处理,ReactInstanceManager实例是通过 MainApplication 类中初始化的 ReactNativeHost 实例获取,在分析 ReactInstanceManager 之前,先跟进 ReactNativeHost 源码看一看:
ReactNativeHost
package com.facebook.react;
/**
private final Application mApplication;
private @Nullable ReactInstanceManager mReactInstanceManager;
protected ReactNativeHost(Application application) {
mApplication = application;
}
/**
/**
/**
/**
for (ReactPackage reactPackage : getPackages()) {
builder.addPackage(reactPackage);
}
String jsBundleFile = getJSBundleFile();
if (jsBundleFile != null) {
builder.setJSBundleFile(jsBundleFile);
} else {
builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName()));
}
ReactInstanceManager reactInstanceManager = builder.build();
return reactInstanceManager;
}
protected final Application getApplication() {
return mApplication;
}
protected @Nullable
JSIModulePackage getJSIModulePackage() {
return null;
}
/**
/**
/**
/**
/**
ReactInstanceManager
CatalystInstance
JSBundleLoader
CatalystInstanceImpl
CatalustInstanceImpl.cpp
NativeToJsBridge.cpp