理解上下文 Context

Context理解

Context理解为上下文对象,是一个应用程序环境信息的接口,也就是说通过Context对象来保存应用相关信息。ActivityServiceApplication都间接继承自Context,Context是一个抽象类,内部定义了很多方法和静态常量,它的具体实现类是ContextImpl。通过下图了解Context的体系。

Context继承关系

ContextImplContextWrapper都继承自Context,ContextWrapper内部持有一个具体指向ContextImpl对象的mBase变量,两者使用了装饰者模式,ContextWrapper是装饰者,相关方法的调用最终都会调用ContextImpl相关方法。

ServiceContextThemeWrapperApplication都继承自ContextWrapper。由于ContextThemeWrapper和主题有关,所以Activity继承了它。这样我们通过ActivityServiceApplication上下文的调用基本都委托到ContextImpl实例的相关方法的调用。

Application Context的创建

在创建Activity的时候,会调用ActivtyThreadperformLaunchActivity函数。

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
//这里的packageInfo是LoadedApk对象
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}

ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}

if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
//创建Activity Context
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
//创建Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
......
}

try {
//创建Application
Application app = r.packageInfo.makeApplication(false, mInstrumentation);

if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}

Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}

appContext.getResources().addLoaders(
app.getResources().getLoaders().toArray(new ResourcesLoader[0]));

appContext.setOuterContext(activity);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken);

if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
//调用了Activity的onCeate函数
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
mLastReportedWindowingMode.put(activity.getActivityToken(),
config.windowConfiguration.getWindowingMode());
}
r.setState(ON_CREATE);
synchronized (mResourcesManager) {
mActivities.put(r.token, r);
}

} catch (SuperNotCalledException e) {
throw e;

} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}

return activity;
}

LoadedApk对象用于缓存当前加载应用程序相关信息。这里将LoadedApk对象保存到了ActivityClientRecord对象的packageInfo变量。performLaunchActivity函数涉及到了ActivityApplcation的创建。由于这里分析Application上下文,所以只关心Application的创建,即调用LoadedApkmakeApplication函数。

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
42
43
44
45
46
47
48
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
//如果不是第一次调用,直接返回已经创建好的Application实例
if (mApplication != null) {
return mApplication;
}

Application app = null;

String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";//可以看到Application的类名
}

try {
final java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"initializeJavaContextClassLoader");
initializeJavaContextClassLoader();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
......
//创建ContextImpl实例
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
NetworkSecurityConfigProvider.handleNewApplication(appContext);
//创建Application实例
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
//ContextImpl实例也引用Application实例
appContext.setOuterContext(app);
} catch (Exception e) {
......
}
mActivityThread.mAllApplications.add(app);
//赋值给Application变量
mApplication = app;

if (instrumentation != null) {
try {
//回调Application的onCreate函数
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
......
}
}
return app;
}

先判断Application对象mApplication是否为null,第一次调用该函数为null,此时为创建该实例。然后通过ContextImpl.createAppContext创建出了ContextImpl的实例,也就是Applicaton Context

再通过Instrumentation对象的newApplication函数创建出Application对象,newApplication函数有两个重载函数,其逻辑最终调用下面两行代码。通过反射创建Application实例,并调用其attach函数,并将前面创建好的ContextImpl实例传递进去。

1
2
Application app = (Application)clazz.newInstance();
app.attach(context);

而在attach函数中,通过attachBaseContext函数把context赋值给了ContextWrappermBase变量。因为Application类是ContextWrapper的子类,这样在创建Application实例时,其内部就持有了ContextImpl的对象,从而可以使用ContextImpl对象相关方法。从而Application可以用来代表Application Context。到这里Application Context就创建完毕了。

1
2
3
4
final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

而我们平常通过Application实例getApplicationContext函数来获取应用的上下文。实际是调用了其父类ContextWrapper

1
2
3
public Context getApplicationContext() {
return mBase.getApplicationContext();
}

这里的mBase指的是ContextImpl实例。

1
2
3
4
public Context getApplicationContext() {
return (mPackageInfo != null) ?
mPackageInfo.getApplication() : mMainThread.getApplication();
}

由于此时应用已经创建,所以mPackageInfo不为null,从而调用LoadedApk对象的mPackageInfogetApplication函数。

1
2
3
Application getApplication() {
return mApplication;
}

也就是我们前面创建的Applicaton对象。

Activity Context的创建

通过上一节我们知道,在ActivityThread类的performLauncherActivity函数会创建Activity实例和对应的上下文。

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
42
43
44
45
46
47
48
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
//创建Activity Context
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
//创建Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
......
}

try {
......
appContext.setOuterContext(activity);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken);

......
//调用了Activity的onCeate函数
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
}
...
} catch (SuperNotCalledException e) {
...
} catch (Exception e) {
...
}

return activity;
}

可以看到整体的逻辑的和Application Context的创建类似。通过createBaseContextForActivity函数创建ContextImpl的实例,通过Instrumentation类的newActivity函数创建Activity对象,然后通过Activity的对象的attach函数,将ContextImpl对象设置到Activity对象中,通过ContextImpl类的setOuterContext函数,将Activity实例设置给ContextImpl对象,达到两者相互应用,可以调用彼此的方法。

createBaseContextForActivity函数通过ConextImpl类方法createActivityContext创建了ContextImple实例,createActivityContext函数也是直接new一个ContextImpl实例。

1
2
3
4
5
6
7
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
...
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
...
return appContext;
}

接着看Instrumentation类的newActivity函数,

1
2
3
4
5
6
7
8
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
String pkg = intent != null && intent.getComponent() != null
? intent.getComponent().getPackageName() : null;
return getFactory(pkg).instantiateActivity(cl, className, intent);
}

getFactory函数。

1
2
3
4
5
6
7
8
9
10
11
private AppComponentFactory getFactory(String pkg) {
if (pkg == null) {
return AppComponentFactory.DEFAULT;
}
if (mThread == null) {
return AppComponentFactory.DEFAULT;
}
LoadedApk apk = mThread.peekPackageInfo(pkg, true);
if (apk == null) apk = mThread.getSystemContext().mPackageInfo;
return apk.getAppFactory();
}

最终还是调用了AppComponentFactory.DEFAULTinstantiateActivity函数新建Activity实例。定位到AppComponentFactory类的instantiateActivity函数。直接通过类加载新建了Activity实例。

1
2
3
public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,@Nullable Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Activity) cl.loadClass(className).newInstance();
}

回到Activity类的attach函数绑定Context

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
//注释1
attachBaseContext(context);

mFragments.attachHost(null /*parent*/);
//注释2
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(mWindowControllerCallback);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
mUiThread = Thread.currentThread();

mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mAssistToken = assistToken;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances != null) {
mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}

mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;

mWindow.setColorMode(info.colorMode);
mWindow.setPreferMinimalPostProcessing(
(info.flags & ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING) != 0);

setAutofillOptions(application.getAutofillOptions());
setContentCaptureOptions(application.getContentCaptureOptions());
}

attach函数给Activity对象创建了PhoneWindow对象,即程序窗口Window的实现类,并设置了很多回调,这样像点击,焦点等事件都会通过Window回调到Activity中。回到Context分析,通过attachBaseContext函数设置Context函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Activity
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
if (newBase != null) {
newBase.setAutofillClient(this);
newBase.setContentCaptureOptions(getContentCaptureOptions());
}
}
//ContextThemeWrapper
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
}
//ContextWrapper
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}

通过向上一层一层的调用,最终还是将ContextImpl实例设置给了ContextWrappermBase变量。与Application Context的设置是一致的。

Service Context的创建

Service Context的创建可以直接定位到ActivityThread类的handleCreateService函数,其逻辑与ActivityApplication的上下文创建是类似的。感兴趣的同学可以自己分析,当做一个彩蛋。

总结

通过Context创建的分析,都是创建ContextImpl的实例,其保存着Application或者ActivityService相关环境信息,从而被从称为对应的上下文。Context在一个应用程序的数量,等于Activity数量+Service数量+1个Application数量总和。