我们一般在写一个Activity的时候都会有在onCreate()方法中看到这么一个方法:setContentView(),今天就以setContentView()方法开始看看这经常出现的代码端是干什么的:
1 setContentView
@Override
protected void onCreate(Bundle savedInstanceState) {
...
setContentView(R.layout.activity_main);
...
}
2 getWindow().setContentView()
3 initWindowDecorActionBar()
我们点进入setContentView(),会跳转到Activity类中,在Activity中的setContenView()方法中首先通过getWindow()来获取一个Window对象,然后调用他的setContenView()方法。最后调用了initWindowDecorActionBar()方法。
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
2.1 setContentView
我们先看看getWindow().setContentView(layoutResID);在之前的Android_activity事件分发流程分析中也有过分析,getWindow他其实就是获取以个PhoneWindow,接下来我们来到PhoneWindow类中,看看里面是怎么实现setContentView()的:
public void setContentView(int layoutResID) {
...
if (mContentParent == null) {
installDecor();
}
...
mLayoutInflater.inflate(layoutResID, mContentParent);
...
}
2.1.1 insatllDecor()
我们看上面的代码中先判断没ContentParent是否为空,[ContentParent看名字应该是contentView的parent,是ViewGroup类型,就是个container来装contentview的] 如果为空的话,就执行installDecor();mContentParent是放置窗口内容的视图。它要么是mDecor本身,要么是mDecor的子view.
我们接下来看看insatllDecor()方法里面做了些什么:
private void installDecor() {
...
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
}
...
}
在insatllDecor()方法中,就是调用generateLayout()创建新的mContentView。接下来我们看generateLayout方法是怎么创建mContentView的:
2.1.1.1 generateLayout()
protected ViewGroup generateLayout(DecorView decor) {
...
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
...
}
在generateLayout()方法中直接通过ID_ANDROID_CONTENT常量来获取,其中ID_ANDROID_CONTENT是XML布局文件中的主布局应具有的ID。就是此时就是加载了xml布局文件,
2.1.2 mLayoutInflater.inflate(layoutResID, mContentParent)
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
return inflate(resource, root, root != null);
}
...
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean
attachToRoot) {
final Resources res = getContext().getResources();
final XmlResourceParser parser = res.getLayout(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
}
infater的主要工作就是解析一个具体的XML资源文件来填充view层级,也就吧我们的布局XML文件实例化为其相应的view对象.然后将view对象放进mContentParent中.为接下来得显示做准备.
所以Activity要想将布局文件显示出来,需要将布局文件setContentView.这就是我们Activity中常见的代码段setContentView(R.layout.activity_main)的实现和作用