Context

上下文,场景,Context是维持Android程序中各组件能够正常工作的一个核心功能类


把“场景”抽象为Context类,他们认为用户和操作系统的每一次交互都是一个场景,比如打电话、发短信,这些都是一个有界面的场景,还有一些没有界面的场景,比如后台运行的服务(Service)。一个应用程序可以认为是一个工作环境,用户在这个环境中会切换到不同的场景。

用来获取一些公共资源,例如资源文件,应用包信息等;

或者用来启动 Activities, 注册广播监听器,发送广播等。

1
2
3
4
5
6
//1
Activity extends ContextThemeWrapper
//2
ContextThemeWrapper / Application / Service extends ContextWrapper
//3
ContextImpl / ContextWrapper extends Context

ContextWrapper的成员变量mBase是ContextImpl类型的
ContextWrapper采用代理模式,各个方法中会通过mBase调用ContextImpl内的方法

  • Context:是一个抽象类,定义一系列与系统交互的接口。
  • ContextWrapper:继承自 Context 抽象类,是 Context 类的包装类(装饰器模式),内部维护一个 Context 类型的成员变量 mBase 指向一个 ContextImpl 对象,ContextWrapper 里面的方法调用是通过 mBase 来调用 ContextImpl 里面的方法,这里用到了代理模式。
  • ContextImpl:继承自 Context 抽象类,实现了 Context 类中的抽象方法,是 Context 类的具体实现类。它为 Activity 及其它应用组件提供上下文环境,应用中使用到的 Context 的方法就是其实现的。
  • ContextThemeWrapper:继承自 ContextWrapper 类,在 ContextWrapper 的基础上增加与主题 Theme 相关的逻辑,即可以指定 Theme 的 Context 包装类,用于在 View 构造时为其提供 Theme 属性集。

ContextImpl 实现类中涉及的主要核心类是:ActivityThread、LoadedApk、PackageManager 和 ResourcesManager,这几个类都是单例的,一个应用程序进程中是共用同一个对象的。

Activity 继承自 ContextThemeWrapper,Application、Service 继承自 ContextWrapper,它们直接或间接的继承自 ContextWrapper 类,因此也拥有了一个 Context 类型的成员变量 mBase 指向一个 ContextImpl 对象,ContextImpl 是 Context 类的具体实现类,所以也都拥有了 Context 提供的所有功能。


1.Activity的this跟getBaseContext区别。

前者是Activity对象本身,后者是通过attachBaseContext传入的ContextImpl对象mBase,两者功能是一样的,通过this最终还是会调到mBase对象中。

2.getApplication和geApplicationContext区别。

两者都是返回Application对象,前者是Activity和Service里面的方法,后者是Context中定义的方法。

3.应用组件的构造,onCreate、attachBaseContext的执行顺序。

先是组件构造,接着attachBaseContext,传入ContextImpl对象,最后是onCreate方法。

4.ContextWrapper中的mBase变量是如何实例化的(分activity和application)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41


//Activity:
//ActivityThread#handleLaunchActivity
//ActivityThread#performLaunchActivity
ContextImpl appContext = createBaseContextForActivity(r);

activity.attach(appContext,…)

//Activity#attach
attachBaseContext(context);

//ContextThemeWrapper#attachBaseContext
super.attachBaseContext(newBase);

//ContextWrapper#attachBaseContext
protected void attachBaseContext(Context base) {
mBase = base;
}


//Application:
//ActivityThread#handleLaunchActivity
//ActivityThread#performLaunchActivity
Application app = r.packageInfo.makeApplicationInner(false, mInstrumentation);

//LoadedApk#makeApplication
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);

//Instrumentation#newApplication
app.attach(context);

//Application#attach
attachBaseContext(context);

//ContextWrapper#attachBaseContext
protected void attachBaseContext(Context base) {
mBase = base;
}