出处:2018年vivo春招
问题链接:https://www.nowcoder.com/discuss/131676?type=2&order=0&pos=1&page=1
本文时间:2019.05.08
解题参考:https://blog.youkuaiyun.com/qinjuning/article/details/7226787
https://blog.youkuaiyun.com/qinjuning/article/details/7110211/
https://www.jianshu.com/p/c151efe22d0d
----------------------------------------- 我的理解 -----------------------------------------
一、在绘制View之前顺便提下setContentView(int resId)的一个过程
setContentView(int resId)是将Activity的布局文件显示在屏幕上,这个过程可以简述如下:
1.在Activity.setContentView(int resId)中调用PhoneWindow.setContentView(int resId),在其中,如果是第一次调用,那么需要安装DecorView和初始化mContentParent;否则,清空mContentParent中的内容。然后将资源文件通过LayoutInflater的inflate方法来将其转换为View树,并将其添加到mContentParent中。
2.在将资源文件添加到mContentParent中之前,还有一些布局步骤:(由DecorView来完成)
确定窗口类型,既是否有标题栏等等;
选择窗口风格对应的布局文件
DecorView将该布局文件添加进去,因为DecorView是根视图;
DecorView获取id为content的FrameLayout传给mContentParent
3.通过回调Activity的handleResumeActivity()来调用Activity的makeVisiable()方法来显示创建的视图族。
二、View的绘制分为三个过程:
1.Measure:测量View的大小
对整个View树进行递归,通过View中measure()方法,来计算View的大小;如果有ViewGroup,需要重写 onMeasure()来遍历计算其中每个子View的大小;
2.Layout:确定View在父容器中的位置
调用View的layout()方法来设置其坐标,其中起作用的是:setFrame()设置子View在父视图的坐标轴和 onLayout()设置布局;
3.Draw:将View绘制出来
调用draw()绘制View树,并不是每次绘制都会重新绘制每个View树的视图,而只绘制需要重新绘制的视图,可根据View类内部变量的标志位DRAWN来决定是否重新绘制;当有包含该标志位时就需要重新绘制。
------------------------------------ 最后 --------------------------------
我的解答比较简单,没有涉及源码和流程图等,主要是考虑的是面试时概括地回答面试官的问题,想要深入学习的,可以参考以上三篇博文,都是很优秀的博文,可以帮助我们理解一些细节。