Android高级UI之 从setContentView了解Android UI绘制流程

从setContentView了解Android UI绘制流程

初学android的朋友可能会有这样一种疑问,为什么在setContentView方法里指定对应的layout资源,就能把对应的布局加载到屏幕上。那么,咱们现在就开始从源码来分析这样一个问题。

首先,在onCreate方法里面,调用了setContentView方法,这个方法是来自Activity的。我们进入到Activity的源码:
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}

这里调用了getWindow的setContentView方法,那getWindow返回了一个Window对象,而Window是一个抽象类,它的唯一子类叫做PhoneWindow,那么这个window是什么时候被赋值的呢?是在attach里面直接new出来的
mWindow = new PhoneWindow(this, window, activityConfigCallback)

我们进入到PhoneWindow看一下setContentView方法。

这个方法主要做了两件事:
1.installDecor
installDecor这个方法干了两件事
1.1 generateDecor
这里实例化了一个DecorView ,DecorView继承自FrameLayout,用来装载我们的页面布局
1.2 generateLayout
如果没有特殊情况的话,是将R.layout.screen_simple这样一个布局加载到DecorView中
布局文件如下:是一个纵向布局 ViewStup用于摆放action bar,而FrameLayout用于摆放我们布局文件中的布局





这一步骤完成之后,mContentParent就不为null了,mContentParent实际上是一个ViewGroup,它对应的类型是R.id.content,在R.layout.screen_simple中对应的实际上就是一个FrameLayout。
2.将setContentView传入的layout解析并绘制
主要代码就是 mLayoutInflater.inflate(layoutResID, mContentParent);

我们来看一下这个方法:

final XmlResourceParser parser = res.getLayout(resource);
try {
        return inflate(parser, root, attachToRoot);
} finally {
        parser.close();
}
这个方法最终返回一个View,也就是向mContentParent中添加子View。
主要代码 :
    View temp = createViewFromTag(root, name, inflaterContext, attrs);
    temp.setLayoutParams(params);
    rInflateChildren(parser, temp, attrs, true);
    root.addView(temp, params);

其中涉及到的xml解析可见下图


LayoutInflater.png

这样,我们整个布局就加载到了对应的Activity当中了,那么,布局是什么时候开始绘制,如何绘制到屏幕上的呢?请看下回分解。

总结:最终Activity的层次结构可以总结为下图:


activity.jpg

你可能感兴趣的:(Android高级UI之 从setContentView了解Android UI绘制流程)