调用了 ContextImpl.createActivityContext()
方法。
static ContextImpl createActivityContext(ActivityThread mainThread,
LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId,
Configuration overrideConfiguration) {
…
// 创建 ContextImpl 对象
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
activityToken, null, 0, classLoader);
…
final ResourcesManager resourcesManager = ResourcesManager.getInstance();
context.setResources(resourcesManager.createBaseActivityResources(activityToken,
packageInfo.getResDir(),
splitDirs,
packageInfo.getOverlayDirs(),
packageInfo.getApplicationInfo().sharedLibraryFiles,
displayId,
overrideConfiguration,
compatInfo,
classLoader));
context.mDisplay = resourcesManager.getAdjustedDisplay(displayId,
context.getResources());
return context;
}
装饰类 ContextWrapper 真正需要的 ContextImpl 对象现在已经创建出来了,但是还没有绑定到 Activity 。继续看 Activity.attach()
方法,注意attach()
方法的第一个参数就是刚刚创建出来的 ContextImpl 对象。
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) {
// 回调 attachBaseContext()
attachBaseContext(context);
…
// 创建 PhoneWindow
mWindow = new PhoneWindow(this, window, activityConfigCallback);
…
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
…
}
你对 attachBaseContext()
方法应该还有印象。ContextWrapper 正是通过这个方法给 mBase
对象赋值,拿到真正的 ContextImpl 对象。到这里,整个逻辑就通顺了。
注意
attach()
方法中的setWindowManager()
方法中的 mToken 参数,这决定了 Application Context 无法创建和显示 Dialog 。后续会进行详细分析。
再回头看看文章开头的问题。
Log.e(“context”, "getApplication in Activity: " + getApplication().getClass().getName());
Log.e(“context”, "getApplicationContext in Activity: " + getApplicationContext().getClass().getName());
Log.e(“context”, "getBaseContext