当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;
}

@Overrideprotected List getPackages() {  return Arrays.asList(      new MainReactPackage()  );}@Overrideprotected 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

更多相关文章

  1. Android(安卓)拦截Home键的常用方法
  2. Graphical layout无法正确显示的解决方法
  3. android中的对话框之二:各种系统对话框的使用实例
  4. android ActionBar-PullToRefresh 下拉刷新的使用方法
  5. android之简单数据存储Preference
  6. 【Android(安卓)开发】:Android中普通按钮的使用方法
  7. 解决android.content.res.Resources NotFoundException的一个方
  8. Android(安卓)Studio中TextView文本过长滚动显示方法
  9. Android(安卓)BLE 总结-源码篇(BluetoothLeAdvertiser)

随机推荐

  1. Android获取webView快照与屏幕截屏的方法
  2. android命令行下创建虚拟设备avd
  3. Android 资源简介(四) ClipDrawable
  4. Android(安卓)native 内存泄露检测
  5. Android进程与线程的概念
  6. android 控件的隐藏和显示
  7. Android 8.1 关机充电动画(一)模式选择
  8. Android使用Handler实时更新UI
  9. 浅谈android的selector 背景选择器
  10. x86平台编译Android