private void installDecor() {
…
if (mDecor == null) {
//实例化DecorView
mDecor = generateDecor(-1);
…
}
} else {
mDecor.setWindow(this);
}
if (mContentParent == null) {
//获取Content
mContentParent = generateLayout(mDecor);
}
…
}
protected DecorView generateDecor(int featureId) {
…
return new DecorView(context, featureId, this, getAttributes());
}
通过generateDecor()
new一个DecorView
,然后调用generateLayout()
获取DecorView
中content
,最终通过inflate
将Activity
视图添加到DecorView
中的content
中,但此时DecorView
还未被添加到Window
中。添加操作需要借助ViewRootImpl
。
ViewRootImpl
的作用是用来衔接WindowManager
和DecorView
,在Activity
被创建后会通过WindowManager
将DecorView
添加到PhoneWindow
中并且创建ViewRootImpl
实例,随后将DecorView
与ViewRootImpl
进行关联,最终通过执行ViewRootImpl
的performTraversals()
开启整个View树的绘制。
关于Activity在何时将DecorView添加到Window以及何时创建 ViewRootImpl,这块内容牵扯面比较广,涉及到Activity启动流程、ActivityManagerService(AMS)、WindowManagerService(WMS),内容太过于深入加上作者能力有限就不误人子弟了。如有兴趣推荐查阅刘皇叔《Android进阶解密》,书中对这方面内容讲解还是比较全面的 。
2. 绘制过程
从第一小节可知,View的绘制是从ViewRootImpl
的performTraversals()
方法开始,从最顶层的View(ViewGroup)
开始逐层对每个View
进行绘制操作,下面来看一下该方法部分源代码:
private void performTraversals() {
…
//measur过程
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
…
//layout过程
performLayout(lp, desiredWindowWidth, desiredWindowHeight);
…
//draw过程
performDraw();
}
这方法大概有几百行,机智的作者抽出三句精华呈现给大家~~~
- measure:为测量宽高过程,如果是ViewGroup还要在onMeasure中对所有子View进行measure操作。
- layout:用于摆放View在ViewGroup中的位置,如果是ViewGroup要在onLa