本章我们来分析从Activity.setContentview()到Activity.onResume()的源码,先来个总结:
- 1 setContentView(): 初始化DecorView,并没有添加到Window上
- 2 onResume()时,Activity并没有添加到屏幕上,onResume()之后才会添加到屏幕上,所以在onResume()里面获取View的宽高不一定能获取到
- 3 由于本章不涉及Activity的启动过程,我们假设已经创建了Window、Context等前置的东西
不BB,上代码
Activity的setContentView():
public void setContentView(int layoutResID) {
//直接用widnow的setContentView()
getWindow().setContentView(layoutResID);
//初始化ActionBar
initWindowDecorActionBar();
}
//getWindow直接返回mWindow
public Window getWindow() {
//Window的赋值是PhoneWindow,在Activity的attach里面会创建,我们后面会讲
return mWindow;
}
//PhoneWindow的setContentView
public void setContentView(int layoutResID) {
//mContentView是个ViewGroup
if (mContentParent == null) {
//1 初始化DecorView
installDecor();
}
//..省略部分代码..
//2 填充布局到mContentParent
mLayoutInflater.inflate(layoutResID, mContentParent);
}
复制代码
先来看1: installDecor
//我们只看主线代码
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
//创建DecorView
mDecor = generateDecor(-1);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
mDecor.setWindow(this);
}
if (mContentParent == null) {
//生成mContentParent
mContentParent = generateLayout(mDecor);
//**省略部分代码**
}
}
//DecorView继承自FrameLayout
protected DecorView generateDecor(int featureId) {
//**省略获取context的代码**
//直接创建并返回
return new DecorView(context, featureId, this, getAttributes());
}
//接着来看mContentParent的生成代码,主要逻辑是:根据主题生成不同的ViewGroup并返回,代码很长,只贴出关键部分
protected ViewGroup generateLayout(DecorView decor) {
//**省略部分代码**
int layoutResource;
int features = getLocalFeatures();
//直接看我们最熟悉的ACTION_BAR相关的
if((features & (1 << FEATURE_NO_TITLE)) == 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
R.attr.dialogTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
layoutResource = a.getResourceId(
R.styleable.Window_windowActionBarFullscreenDecorLayout,
R.layout.screen_action_bar);
} else {
//直接看这里把,指定了一个布局文件(布局文件代码,可以直接在后面看到)
//这个布局文件中有个android:id = "@android:id/content"的FrameLayout
layoutResource = R.layout.screen_title;
}
}
//添加这个布局到DecorView
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
//findView