从源码分析 Activity 的 onCreate 方法的 setContentView 都做了什么。
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);
// 如果需要的话,初始化 ActionBar
initWindowDecorActionBar();
}
其中 getWindow() 返回的是 PhoneWindow, 它的初始化是在 Activity.attach 时赋值的
mWindow = PolicyManager.makeNewWindow(this); // 实际执行的在 Policy.makeNewWindows
下面看 PhoneWindow.setContentView, 这里做的就是初始化 DecoreView 和加载给定的 layout id.
public void setContentView(int layoutResID) {
if (mContentParent == null) {
// 初始化 DecoreView, 这里会赋值 mContentParent
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
// 是否有 transition
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
// 直接加载 layoutResID,到这里 layout 已加载完毕
mLayoutInflater.inflate(layoutResID, mContentParent);
}
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
接下来我们就来看 installDecor 方法做了什么吧,
private void installDecor() {
// 初始化 mDecor
if (mDecor == null) {
mDecor = generateDecor();
// ...
}
// 初始化 mContentParent
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
// Set up decor part of UI to ignore fitsSystemWindows if appropriate.
mDecor.makeOptionalFitsSystemWindows();
// 填充 title 和 content
final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
R.id.decor_content_parent);
// ...
if (mDecor.getBackground() == null && mBackgroundFallbackResource != 0) {
mDecor.setBackgroundFallback(mBackgroundFallbackResource);
}
if (hasFeature(FEATURE_ACTIVITY_TRANSITIONS)) {
// 设置一些 transition
// ...
}
}
}
初始化 DecoreView 方法中就是 new 了一个 DecoreView, 下面看初始化 mContentParent 的方法,这一段代码比较多,就主要介绍一下
protected ViewGroup generateLayout(DecorView decor) {
// 先设置 style
// ...
// 根据版本和设置来决定是否需要菜单
// ...
mDecor.startChanging();
// 添加指定需要的 View(title, actionBar, 等)
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;
// 获取 contentParent
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
// 设置背景,title, 颜色 等
mDecor.finishChanging();
return contentParent;
}
这样也就可以理解下图了: