导读:
本篇文章的前半部分为源码分析,后半部分为一个例子,在例子中我们会遇到一些问题,从而回答前半部分留下的问题!
源码分析:
说到Activity的setContentView,咱们直接找到一个Activity中的setContentView点进去看看!
public void setContentView(View view) {
getWindow().setContentView(view);
initActionBar();
}
点进来之后我们发现它里边调用了getWindow.setContentView,我们点击getWindow看看里面是什么!
public Window getWindow() {
return mWindow;
}
返回了一个Window对象,这个mWindow就是Window的子类PhoneWindow,每一个Activity都有一个PhoneWindow对象,至于他们是怎么联系起来的我们就不去研究了,好了现在我们来到了第一层!
我们在PhoneWindow中找到了setContentView的实现
public class PhoneWindow extends Window implements MenuBuilder.Callback {
//...
//...
//...
//老大
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
mLayoutInflater.inflate(layoutResID, mContentParent);
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
//老二
@Override
public void setContentView(View view) {
setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
}
//和老三
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
mContentParent.addView(view, params);
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
//...
//...
//...
}
我们看到首先判断了mContentParent,那么这个mContentParent是个什么呢?当mContentParent为空的时候,会执行installDecor()方法,那么我们肯定是到installDecor中去找答案咯,点进去!
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();
//...
}
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
//...
}
}
}
}
我把代码能删的都给删了,我们看见mContentParent为空的时候,会执行generateLayout()方法,同时需要传入一个mDecor,那么mDecor是什么东西呢,我们往上面看,mDecor是通过generateDecor()方法创建出来的,那我们自然得先到generateDecor()中一探究竟!
protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
new了一个DecorView对象,DecorView就是我们界面中最顶层的View了,这个View的结构是这样的!
DecorView继承于FrameLayout,然后它有一个子view即LinearLayout,方向为竖直方向,其内有两个FrameLayout,上面的FrameLayout即为TitleBar之类的,下面的FrameLayout即为我们的ContentView,所谓的setContentView就是往这个FrameLayout里面添加我们的布局View的!现在我们可以画出第二层了!