一、Context 简介
Google 正式推出 Kotlin 前,主流 Android 应用都是使用 Java 语言来编写的。那么大家有没有思考过,一个 Android 程序和一个Java 程序,他们的区别在哪里?划分界限又是什么呢?其实简单点分析,Android 程序不像 Java 程序一样,随便创建一个类,写个 main() 方法就能运行了,而是要有一个完整的 Android 工程环境。在这个环境下,Activity 、Service 、 ContentProvider 、BroadcastReceiver 等系统组件并不是像普通的 Java 程序 new 一下就能创建实例了,而是要有它们各自的上下文环境,也就是我们这里讨论的 Context 。可以这样讲,Context 是维持 Android 程序中各组件能够正常工作的一个核心类。
Android 官方注释:
Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.
译文:Context 是有关应用程序环境的全局信息的接口。这是一个抽象类,其实现由 Android 系统提供。 它允许访问特定于应用程序的资源和类,以及对应用程序级别操作的上调,例如启动 Activity,发送广播和接收 Intent 等。
既然 Context 是一个抽象类,那么具体使用中肯定要有它的实现类,通过查看 Android 官方文档我们得知 Context 的继承结构如下图所示:
通过关系图得知,Context 有三个具体的实现子类:MockContext 、ContextWrapper 和 ContextImpl 。 MockContext 类,正如官方注释“A mock Context class. All methods are non-functional and throw UnsupportedOperationException. You can use this to inject other dependencies, mocks, or monitors into the classes you are testing. ”,是一个虚假的 Context, 所有的方法都没有具体实现,主要用于单元测试中,这里不做过多探讨。ContextWrapper 类,如其名所言,这是一个包装类,ContextWrapper 构造函数中必须包含一个真正的 Context 引用,同时 ContextWrapper 中提供了attachBaseContext() 用于给 ContextWrapper 对象指定真正的 Context 对象,调用 ContextWrapper 的方法都会被转向其所包含的真正的 Context 对象。ContextThemeWrapper类,如其名所言,其内部包含了与主题(Theme)相关的接口,这里所说的主题是指在 AndroidManifest.xml 中通过 android:theme 为 Application 元素或者 Activity 元素指定的主题。当然只有 Activity 才需要主题,Application 是不需要主题的,因为 Application 是没有界面的,所以 Application 直接继承于 ContextWrapper,Service 同理。ContextImpl 类则真正实现了 Context 中所有的抽象方法,应用程序中所调用的各种 Context 类的方法,其实现均来自于该类。
Context 类部分源码:
/**
* Interface to global information about an application environment. This is
* an abstract class whose implementation is provided by
* the Android system. It
* allows access to application-specific resources and classes, as well as
* up-calls for application-level operations such as launching activities,
* broadcasting and receiving intents, etc.
*/
public abstract class Context {
/**
* Returns an AssetManager instance for the application's package.
* <p>
* <strong>Note:</strong> Implementations of this method should return
* an AssetManager instance that is consistent with the Resources instance
* returned by {@link #getResources()}. For example, they should share the
* same {@link Configuration} object.
*
* @return an AssetManager instance for the application's package
* @see #getResources()
*/
public abstract AssetManager getAssets();
/**
* Returns a Resources instance for the application's package.
* <p>
* <strong>Note:</strong> Implementations of this method should return
* a Resources instance that is consistent with the AssetManager instance
* returned by {@link #getAssets()}. For example, they should