view的绘制包括三个过程:measure,layout,draw:
(1)measure:
整个View的组成可以看成是一棵树,measure过程是从根节点(PhoneWindow$DecorView)遍历所有节点,如果一个View还有子View,则measure子View,直到所有的子View完成measure操作之后,再measure自己,也就是说measure操作是一个后序操作。由父节点给每一个节点的孩子节点节进行measure操作,即在ViewGroup中的measureChildWithMargin()中调用child.measure()方法,而根节点(PhoneWindow$DecorView)不需要measure,因为它默认占满了整个屏幕。然后执行到同一操作层次的onMeasure()方法,如果该View还有子View,则调用子View的measure()方法。执行每一个非根节点需要走的measure过程:measure()->onMeasure()-> setMeasuredDimension()。这样,每一个view都知道了自己的大小。
其中,measure()/setMeasureDimension()是View的最终类,不能被重载,onMeasure需要子View重载。按照前序遍历所有节点,但是最后设置每一个节点的大小(也就是调用SetMeasureDimension())的过程是后序设置的。
(2)layout:
同理,再一次遍历,对每一个节点的孩子节点layout,根节点不需要layout。同样,每一个非根节点的节点需要走的layout过程:layout()->onLayout()。其中,layout()是View的最终类,不能重载,onLayout()需要子View的重载。按照前序遍历所有节点,但是最后定位每一个节点的位置(也就是调用onLayout())的过程是后序定位的。
(3)draw:
measure和layout过程执行完成之后,从根节点开始draw,每一个节点(包括根节点)都需要这个draw的过程:draw()->drawbackground->onDraw()->dispatchDraw()->onDrawScrollBars().其中,draw(),onDrawScrollBars()是View的最终类,不能重载,而onDraw被各种Widget(View的子类,如TextView,ImageView等)重载,负责画自己的视图。dispatchDraw()被View的子类ViewGroup重载,负责画它的子View,即重复draw的过程,整个过程是一个递归过程。直到布局树中的叶子节点为止。画图过程是前序过程。
ListView的画图过程有些特殊,执行measure操作时,只是针对一个Item(它的子View)和它自己进行measure操作,待到执行onLayout()时再一并执行其余Items的measure和layout操作。
本文深入解析Android应用UI绘制的三个关键步骤:measure、layout和draw,详细阐述了每个阶段的操作过程、重要方法及作用,帮助开发者理解并优化UI性能。

被折叠的 条评论
为什么被折叠?



