View 是 Android 中的试图呈现方式,不能单独存在,必须附在 Window 这个抽象概念上,因此有视图的地方就有 Window。Android 中可以提供的视图的地方有 Activity、Dialog、Toast,还有依托 Window 而实现的视图,比图 PopUpWindow、菜单,下面分析视图元素中 Window 的创建过程。
####Activity 的 Window 创建过程####
- 要分析 Activity 的 Window 的创建过程必须了解 Activity 的启动过程,启动过程很复杂,最终由 ActivityThread 中的 performLaunchActivity 来完成整个启动过程,这个方法创建 Activity 的实例对象,并调用其 attach 方法关联运行过程中所依赖的上下文环境变量。
ActivityThread - - performLaunchActivity - - Activity(实例) - - attach
ActivityThread 类中源码
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(cl,component.getClassName(), r.intent);
...
if(activity !=null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
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);
...
}
- 在 Activity 中的 attach 方法里,系统会创建 Activity 所属的 Window 对象并为其设置回调接口,Window 对象的创建是通过 PolicyManager 的 makeNewWindow 方法实现的。由于 Activity 实现了 Window 的 Callback 接口,因此当 Window 接收到的外界的状态改变就会回调 Activity 的方法。
Activity 源码
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
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);
}
到这里 Window 已经创建完成了,下面分析 Activity 的视图是怎么附属在 Window 上的,由于 Activity 视图是由 setContentView 方法提供,那么只需要看 setContentView 的方法实现即可。
- 如果没有 DecorView ,那么就创建它。
- 将 View 添加到 DecorView 的 mContentParent 中。
- 回调 Activity 的 onContentChanged 方法通知 Activity 视图已经发生改变。
- 将 DecorView 添加到 Window 中,通过 Activity 的 makeVisible 方法完成显示过程。