写点什么

【面试官爸爸】来给我讲讲 View 绘制,腾讯 T2 亲自教你

用户头像
Android架构
关注
发布于: 2021 年 11 月 05 日

“对对对” 我赶紧答应


“行吧,那你讲讲 View 的绘制流程吧”



起一个好头




View 的绘制流程应该是每个初高级 Android 攻城狮必知必会的东西,也是面试必考的内容,每个人都有不同的回答方式。


简单点譬如 measure,layout,draw 分别对应测量,布局,绘制三个过程,高明一点的会引申出 Handler,同步屏障,View 的事件传递,甚至 activity 的启动过程。掌握哪些东西,如何回答,能够给面试官一种清晰,了然于胸的感觉,同时又不会被追问三连一问三不知。各位老爷听我慢慢道来。


“噢噢,View 的绘制啊。这个可以分为顶级 View 的绘制,Viewgroup 的绘制和 View 的绘制三个方面。顶级 View 就是 ViewrootImpl”


将回答的内容分类是体现自己思考能力和知识结构的重要表现。


什么是 ViewRootImpl




相比 Viewgroup 和 View,ViewRootImpl 可能更为陌生,实际开发中我们基本用不到它。那么


什么是 ViewRootImpl 呢?


从结构上来看,ViewRootImpl 和 ViewGroup 其实是一种东西



它们都继承了 ViewParent。ViewParent 是一个接口,定义了一些父 View 的基本行为,比如 requestlayout,getparent 等。不同的是,ViewRootImpl 并不会像 ViewGroup 一样被真正绘制在屏幕上。在 activity 中,它是专门用来绘制 DecorView 的,核心方法是 setView


回答的好好的偏要问我其他问题




提到 DecorView,就不得不说一下 window 了。面试中常常我们提到一个点,或者一个词,面试官会马上引申出这个知识点相关的问题。如果我们只是死记硬背,自顾自背一堆绘制相关的东西而回答不上来,会大大减分。所以储备与必问内容相关的东西对面试和自己的知识体系很有帮助。不少老爷被面试的时候都会被问到一个问题


“activity,window,View 三者之间的关系是什么?”


我们可以通过一张图来说明。



如图所示,window 是 activity 里的一个实例变量,本质是一个接口,唯一的实现类是 PhoneWindow。


activity 的 setContentView 方法实际上是就是交给 phonewindow 去做的。window 和 View 的关系可以类比为显示器显示的内容


每个 activity 都有一个“显示器” window,“显示的内容”就是 DecorView。这个“显示器”定义了一些方法来决定如何显示内容。比如 setTitleColor setTitle 是设置导航栏的颜色和 title , setAllowReturnTransitionOverlap 设置进/出场动画等等。


所以 window 是 activity 的一个成员变量,window 和 View 是“显示器”和“显示内容”的关系。


这就是他们的关系


View 是怎么绘制的




“呦呵,不错嘛,这个比喻不错,看来平时还挺爱思考的。行,你继续说说 View 是怎么绘制的”


在整个 activity 的生命周期中,setContentView 是在 onCreate 中调用的,它实现了对资源文件的解析,完成了 xml 文件到 View 的转化。那么 View 真正开始绘制是在哪个生命周期呢?


答案是 onResume 结束后


他们的关系在源码中一目了然。



从源码中可以看到,onResume 之后,ActivityThread 通过调用 activity 中 windowmanager 的 addView 方法,将 decorView 传入到 ViewRootImpl 的 setView 方法中,通过 setView 来完成 View 的绘制。


问题又来了,setView 到底有什么魔法,为什么他就能完成 View 的绘制工作呢?


ViewRootImpl 是如何绘制 View 的




我们再来看一下 setView 方法



简单来说 setView 做了三件事


① 检查绘制的线程是不是创建 View 的线程。这里可以引申出一个问题,View 的绘制必须在主线程吗?


② 通过内存屏障保证绘制 View 的任务是最优先的


③ 调用 performTraversals 完成 measure,layout,draw 的绘制


看到这里,ViewRootImpl 的绘制基本就完成了。其实这也是面试官希望听到的内容。考察的是面试者对 View 绘制体系的理解。


后续 ViewGroup 和 View 的绘制其实是 performTraversals 对整个 ViewTree 的绘制。他们的关系可以用下面这张图表示



考考你对知识的运用




“不错不错,看来你对 Viewrootimpl 的绘制过程掌握的不错嘛,你刚才提到 View 的绘制是在 onResume 之后才开始的,那为什么我在 onCreate 中调用 View.post 方法可以得到 View 的宽高呢”


这个问题乍看挺唬人的。其实看一眼源码大概就明白了



View.post 会判断当前 View 是否已经被添加到 window 上。如果添加了则立即执行 runnable,如果没有被添加则先放到一个队列中存储起来,等添加到 window 上时再执行


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码



而 View 被测量完成后才会 attachToWindow。所以当 post 的 runnable 执行时,View 已经绘制完成了。


MeasureSpec 的理解

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
【面试官爸爸】来给我讲讲View绘制,腾讯T2亲自教你