APP 开发中,我们需要使用 app 的资源,比如文字、图片,Activity、Service或者 broadcastReceiver 等等。时常也会用到
getApplicationContext()
来获取一个 Context 对象。那么这个 Context 到底是什么呢?
Context 类简介
context 含义有语境,上下文,背景,环境等等。 Context 是维持 Android 程序中各组件能够正常工作的一个核心功能类。Context
是一个抽象类。它是一个 app 全局环境的“接口”,由 Android 系统提供继承类(例如 Activity、Service、Application 等)。它能连接到应用的资源,也能使用应用级的操作,比如启动 activity,广播和接收 intent。应用程序中Context的总数目为: 总 Context 个数 = Activity 个数 + Service个数 + 1(Application Context)
Context 的子类 简单的继承关系示意
Context
├── ContextImpl
└── ContextWrapper
├── Application
├── ContextThemeWrapper
│└── Activity
└── Service
从继承关系图中可以看出,Application 类、Service 类和 Activity 类都继承了Context 类。应用程序被启动后,会为应用程序创建一个全局的 Application 对应的 Context 对象。ContextImpl 类是 Context 的真正实现。
ContextWrapper 类是封装类。可以在不改变 ContextImpl 的情况下,为其增加一些自定义操作。ContextWrapper 中的 mBase 实际上是一个 ContextImpl对象。而 ContextImpl 类中的 mOuterContext 是一个 Context 对象,指向相对应的 Activity 或 Service 或 Application。
ContextImpl
Context
是一个抽象类,子类 ContextImpl
实现了Context
的方法;为Activity和其他应用组件提供基本的context对象。 ContextImpl.java (frameworks\base\core\java\android\app)/**
* Common implementation of Context API, which provides the base
* context object for Activity and other application components.
*/
class ContextImpl extends Context { /*...*/ }
ContextWrapper
Wrapper 有封装的意思;
ContextWrapper
是 Context 的封装类 。这里使用了装饰者模式,构造方法中传入了一个 Context 实例。ContextWrapper
持有 ContextImpl
对象。可以在不改变 ContextImpl
的情况下增加一些操作。ContextWrapper.java (frameworks\base\core\java\android\content)
/**
* Proxying implementation of Context that simply delegates all of its calls to
* another Context.Can be subclassed to modify behavior without changing
* the original Context.
*/
public class ContextWrapper extends Context {
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
// ...
}
具体操作中,Application 类、Activity 和 Service 类与
ContextImpl
产生交集。ContextThemeWrapper
允许在封装的 context 中修改主题(theme)
ContextThemeWrapper.java (frameworks\base\core\java\android\view)
/**
* A ContextWrapper that allows you to modify the theme from what is in the
* wrapped context.
*/
public class ContextThemeWrapper extends ContextWrapper { /* ... */ }
其中提供了关于 theme 的方法,app 开发中
android:theme
与此有关。相同的代码,相同的调用,使用不同的 theme 会有不同的效果。getApplicationContext() 和 getBaseContext()
public class ContextWrapper extends Context {
Context mBase;
......
@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}
......
/**
* @return the base context as set by the constructor or setBaseContext
*/
public Context getBaseContext() {
return mBase;
// Don't use getBaseContext(), just use the Context you have.
}
......
}
getApplicationContext() = android.app.Application@39d42b0e
getBaseContext() = android.app.ContextImpl@1f48c92f
getApplicationContext() 从 application 取得 context。getBaseContext() 从实现类 ContextImpl 那得来。
Context 子类创建流程 Application的创建流程
我们把关注点先放在 application 上,暂时忽略源码中的其他信息。
流程描述:
LoadedApk
先通过 classLoader
的 loadClass(className)
获取application 的 class
,再通过 clazz.newInstance()
创建 Application
实例。接着调用 app.attach(context)
方法完成初始化。Application 的 attach 方法里调用了自己的
attachBaseContext(context)
, 把第一步创建的 ContextImpl
实例赋值给 ContextWrapper
的 mBase
成员变量。 到此 Application 实例创建就完成了。Activity的创建 - performLaunchActivity
这里关注的是 Activity 的实例化以及之前的一些准备过程。
【Android入门教程 | 认识 Android Context】流程简析:
主要关注
ActivityThread
的 performLaunchActivity
方法。通过ContextImpl
的 createActivityContext
获得一个 ContextImpl 实例,称为 appContext
。Instrumentation
的 newActivity
返回了一个 Activity 实例。LoadedApk.makeApplication
可以获得当前的 application,如果当前没有则新建一个 application。最后通过 ContextImpl.setOuterContext
和 Activity 的attach
方法,将 ContextImpl 实例与 Activity 实例关联到一起。使用 自定义Application
新建一个 MyApplication 类,继承自 Application
import android.app.Application;
import android.content.Context;
public class MyApplication extends Application {
private static Context context;
public static Context getMyContext() {
return context;
}@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
}
在Manifest中使用MyApplication;
......
即可在不同的地方调用 getMyContext() 方法
MyApplication.getMyContext()
【Android 零基础入门教程视频参考】