Activity是android的四大组件之一,其重要性不言而喻,而且在我们的开发过程中打交道最多的也是它。在设置视图的时候,我们一般都是通过setContentView来加载我们的布局资源的,看起来很简单的一行代码setContentView(),但是实际上里面都做了哪些事情你真的知道吗?
在开始讲解setContentView的源码之前,你首先要弄懂上面的这张图,弄不懂也没关系,但是你需要记住它,这样有利于后面的源码理解。
源码解析
@Override
public void setContentView(int layoutResID) {
// mContentParent即DecorView
// mContentParent是否为空,第一次进来的时候为空
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
mContentParentExplicitlySet = true;
}
private void installDecor() {
mForceDecorInstall = false;
// mDecor是否为空,第一次进来的时候为空
if (mDecor == null) {
// 初始化DecorView
mDecor = generateDecor(-1);
// 省略部分代码
} else {
mDecor.setWindow(this);
}
// mContentParent是否为空,第一次进来的时候为空
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
// 省略部分代码
}
}
// 初始化DecorView
protected DecorView generateDecor(int featureId) {
// 省略部分代码
// 创建DecorView
return new DecorView(context, featureId, this, getAttributes());
}
protected ViewGroup generateLayout(DecorView decor) {
TypedArray a = getWindowStyle();
// 设置 当前Activity配置的主题theme
// 窗口是否是浮动的
mIsFloating = a.getBoolean(R.styleable.Window_windowIsFloating, false);
int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
& (~getForcedWindowFlags());
if (mIsFloating) {
setLayout(WRAP_CONTENT, WRAP_CONTENT);
setFlags(0, flagsToUpdate);
} else {
setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
}
// 窗口是否有标题栏
if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
requestFeature(FEATURE_NO_TITLE);
} else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) {
// Don't allow an action bar if there is no title.
requestFea