当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<ReactPackage> getPackages() {
return Arrays.<ReactPackage>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 中主要完成了三件事:
- (1)实现 ReactApplication 接口,重写 getReactNativeHost 方法,返回ReactNativeHost实例。
- (2)定义并初始化 ReactNativeHost,实现 getUseDeveloperSupport、getPackages、getJSMainModuleName 方法,完成初始化设置。
- (3)在 onCreate 生命周期方法中,调用SoLoader的init方法,启动C++层逻辑代码的初始化加载。
了解完两个文件,我们先从 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;
/**
- Base Activity for React Native applications.
*/
public abstract class ReactActivity extends Activity implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {
private final ReactActivityDelegate mDelegate;
protected ReactActivity() {
mDelegate = createReactActivityDelegate();
}
/**
- 返回从JavaScript注册的主要组件的名称,用于组件的渲染。
*/
protected @Nullable String getMainComponentName() {
return null;
}
/**
- 在构造时调用,如果有自定义委托实现,则覆盖.
*/
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName());
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDelegate.onCreate(savedInstanceState);
}
… 中间省略生命周期、返回事件、权限申请函数
/**
- 获取 ReactNativeHost 实例
*/
protected final ReactNativeHost getReactNativeHost() {
return mDelegate.getReactNativeHost();
}
/**
- 获取 ReactInstanceManager 实例
*/
protected final ReactInstanceManager getReactInstanceManager() {
return mDelegate.getReactInstanceManager();
}
/**
- 加载 JSBundle
*/
protected final void loadApp(String appKey) {
mDelegate.loadApp(appKey);
}
}
ReactActivity类中主要完成这几件事:
- (1)继承 Activity,实现 DefaultHardwareBackBtnHandler、PermissionAwareActivity 两个接口。重写其中的返回事件,及请求权限的方法。
- (2)构造函数中调用 createReactActivityDelegate 方法,传入this、和 getMainComponentName 方法返回值,创建 ReactActivityDelegate实例。
- (3)重写 Activity 生命周期方法,调用 delegate 实例的对应生命周期方法。
- (4)定义获取 ReactNativeHost、ReactInstanceManager 实例方法。
- (5)定义 loadApp方法。
可以看出ReactActivity采用了委托的方式,将所有的行为都交给ReactActivityDelegate去处理,降低耦合提升可扩展性,接下来我们瞎看ReactActivityDelegate是如何定义的
ReactActivityDelegate
package com.facebook.react;
/**
- Delegate class for {@link ReactActivity} and {@link ReactFragmentActivity}. You can subclass this
- to provide custom implementations for e.g. {@link #getReactNativeHost()}, if your Application
- class doesn’t implement {@link ReactApplication}.
*/
public class ReactActivityDelegate {
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());
}
/**
- Get the {@link ReactNativeHost} used by this app. By default, assumes
- {@link Activity#getApplication()} is an instance of {@link ReactApplication} and calls
- {@link ReactApplication#getReactNativeHost()}. Override this method if your application class
- does not implement {@code ReactApplication} or you simply have a different mechanism for
- storing a {@code ReactNativeHost}, e.g. as a static field somewhere.
*/
protected ReactNativeHost getReactNativeHost() {
return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost();
}
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)定义 getReactNativeHost、getReactInstanceManager 方法,获取对应实例。可以看到此处调用的是MainApplication中定义的ReactNativeHost实例。这里也就明白,为什么MainApplication需要实现ReactApplication接口,并重写 getReactNativeHost方法了。如果不实现 ReactApplication,可以把ReactNativeHost定义成全局静态常量即可。
- (2)定义生命周期方法、返回事件方法、权限请求方法。并在方法中调用 ReactInstanceManager 中对应的方法。
- (3)定义 createRootView 方法,在该方法中,通过 new ReactRootView,创建 ReactRootView 实例。
- (4)在 onCreate 生命周期中,判断 mMainComponentName,如果不为 null,则执行 loadApp 方法。所以我们重点来看 loadApp 方法。
- (5)在 loadApp 方法中主要做了三件事:
-
1. 创建 RootView
-
2. 调用 RootView 实例的 startReactApplication 方法,将 ReactInstanceManager 实例、appKey、启动时初始化参数作为参数传递过去
-
3. 将 ReactRootView 设置为 MainActivity 布局视图
-
从 ReactActivityDelegate 方法中,我们了解到很多方法都交给了 ReactInstanceManager 实例去处理,ReactInstanceManager实例是通过 MainApplication 类中初始化的 ReactNativeHost 实例获取,在分析 ReactInstanceManager 之前,先跟进 ReactNativeHost 源码看一看:
ReactNativeHost
package com.facebook.react;
/**
- 包含 ReactInstanceManager 实例的简单类, 在 MainApplication 中定义 或 定义成静态字段使用。
*/
public abstract class ReactNativeHost {
private final Application mApplication;
private @Nullable ReactInstanceManager mReactInstanceManager;
protected ReactNativeHost(Application application) {
mApplication = application;
}
/**
- 获取 或 创建 ReactInstanceManager 实例
*/
public ReactInstanceManager getReactInstanceManager() {
if (mReactInstanceManager == null) {
mReactInstanceManager = createReactInstanceManager();
}
return mReactInstanceManager;
}
/**
- 获取此持有者是否包含{@link ReactInstanceManager}实例
*/
public boolean hasInstance() {
return mReactInstanceManager != null;
}
/**
- 销毁当前实例并释放对其的内部引用,允许它进行GCed
*/
public void clear() {
if (mReactInstanceManager != null) {
mReactInstanceManager.destroy();
mReactInstanceManager = null;
}
}
/**
- 创建 ReactInstanceManager 实例
*/
protected ReactInstanceManager createReactInstanceManager() {
ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
.setApplication(mApplication)
.setJSMainModulePath(getJSMainModuleName())
.setUseDeveloperSupport(getUseDeveloperSupport())
.setRedBoxHandler(getRedBoxHandler())
.setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
.setJSIModulesPackage(getJSIModulePackage())
.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()));
}
ReactInstanceManager reactInstanceManager = builder.build();
return reactInstanceManager;
}
protected final Application getApplication() {
return mApplication;
}
protected @Nullable
JSIModulePackage getJSIModulePackage() {
return null;
}
/**
- 返回 JSBundle 主模块的名称。 确定用于获取JS包的URL来自打包服务器。
- 它仅在启用dev支持时使用。
- 这是创建 ReactInstanceManager 后要执行的第一个文件。
- 默认 index”
*/
protected String getJSMainModuleName() {
return “index”;
}
/**
- 返回捆绑文件的自定义路径。 这是在应该加载bundle的情况下使用的自定义路径。例如“文件://sdcard/myapp_cache/index.android.bundle”
- 默认情况下,它是从指定路径的Android assets目录下加载
*/
protected @Nullable String getJSBundleFile() {
return null;
}
/**
- 返回资产中包的名称。 如果为null,则不指定文件路径捆绑。
- 该方法只能与 getUseDeveloperSupport 一起使用并且将会总是尝试从打包服务器加载JS包。
- 默认为 index.android.bundle
*/
protected @Nullable String getBundleAssetName() {
return “index.android.bundle”;
}
/**
- 返回是否启用dev模式
*/
public abstract boolean getUseDeveloperSupport();
/**
- 返回应用程序使用的 ReactPackage 列表,至少返回 MainReactPackage。
- 如果您的应用使用除默认视图或模块之外的其他视图或模块,您需要在此处添加更多套餐。
*/
protected abstract List getPackages();
}
ReactRootView
ReactInstanceManager
CatalystInstance
JSBundleLoader
CatalystInstanceImpl
CatalustInstanceImpl.cpp
NativeToJsBridge.cpp