2019-02-18
Context 在 Android 开发中是一个很重要的概念,用于提供各种上下文服务。在 React Native 中,它对 Context 进行了扩展。在本文中我们来梳理 React Native 中的各种 Context(ReactContext,ReactApplicationContext)。
这几个 Context 类满足如下继承关系:
ReactContext 在 ContextWrapper 的基础上提供了哪些能力呢?
具体包括如下:
存放 CatalystInstance 实例引用:
方法三个线程的引用:
(从这里我们也能看出,React Native 在运行时启动了 3 条线程。)
存放原生模块异常处理器:
覆写了 getSystemService 的默认行为:
生命周期回调管理:
CopyOnWriteArraySet<LifecycleEventListener> mLifecycleEventListeners
CopyOnWriteArraySet<ActivityEventListener> mActivityEventListeners
ReactApplicationContext 继承自 ReactContext,它在其基础上提供了哪些能力呢?
这个类啥能力也没提供,它唯一的作用就是在构造的时候获取 ApplicationContext。
/** * A context wrapper that always wraps Android Application {@link Context} and * {@link CatalystInstance} by extending {@link ReactContext} */ public class ReactApplicationContext extends ReactContext { // We want to wrap ApplicationContext, since there is no easy way to verify that application // context is passed as a param, we use {@link Context#getApplicationContext} to ensure that // the context we're wrapping is in fact an application context. public ReactApplicationContext(Context context) { super(context.getApplicationContext()); } }
在 React Native 中还有一个类是 ReactApplication,千万不要把它跟 ReactApplicationContext 搞混了!
ReactApplication 是一个接口:
public interface ReactApplication { /** * Get the default {@link ReactNativeHost} for this app. */ ReactNativeHost getReactNativeHost(); }
它的使用场景在创建 Application 时实现这个接口,用于提供 ReactNativeHost。与我们本文中讨论的内容完全不相关。因此我们不详细说它,只要别搞混就行。
在 Android APP 中,如果不写任何代码,我们只能拿到 Android Context,如何转到 ReactContext 呢?
答案在 ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java 的 createReactContext 方法中:
在前面文章中我们梳理过,ReactInstanceManager 是通过一个 Builder 来构建的,构建时传入的一个参数是 Context,它存放在成员变量中:
createReactContext 的具体逻辑在React Native 代码阅读(一):启动流程(Android)的 ReactContext 的创建与绑定一节中已做梳理,这里不再赘述。
其中有一行:
final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);
是用 mApplicationContext 创建了一个 ReactApplicationContext。
上一节中我们分析了 ReactContext 的创建过程。在本节中,我们分析 ReactInstanceManager 是如何使用 ReactApplicationContext 的。
首先,ReactApplicationContext 是在 runCreateReactContextOnNewThread 方法中被创建的。
在方法中首先调用 createReactContext 并创建一个局部变量:
final ReactApplicationContext reactApplicationContext = createReactContext( initParams.getJsExecutorFactory().create(), initParams.getJsBundleLoader());
之后调用:
setupReactContext(reactApplicationContext);
setupReactContext 方法对 reactApplicationContext 进行设置,我们来看它的内部实现:
首先将 reactApplicationContext 存放到 ReactInstanceManager 类的 mCurrentReactContext 成员中:
mCurrentReactContext = Assertions.assertNotNull(reactContext);
之后对 ReactContext 中存放的实例进行了一系列的初始化操作:
至此我们完成了 ReactNative 中 Context 的梳理。
在本文中,我们知道了 ReactContext 与 Android Context 的关系,以及 ReactContext 中提供了哪些服务。
同时我们也分析了 ReactInstanceManager 对 ReactApplicationContext 的使用。在 ReactInstanceManager 中,还有很多方法都需要传入 ReactContext 实例,供其他类使用,有了本文的知识这些都不在话下了。