安卓View的绘制流程和机制

View系统的绘制流程会从ViewRoot的performTraversals()方法中开始,performTraversals()的意思是:执行遍历


View的整个绘制流程可以分为以下三个阶段:

measure: 判断是否需要重新计算View的大小,需要的话则计算;
layout: 判断是否需要重新计算View的位置,需要的话则计算;
draw: 判断是否需要重新绘制View,需要的话则重绘制。
measure()、layout()、draw(),其内部又分别包含了onMeasure()、onLayout()、onDraw()三个子方法。
 

View树的绘制是一个递归的过程,从ViewGroup一直向下遍历,直到所有的子view都完成绘制,那这一切的源头在什么地方(是谁最发起measure、layout和draw的)?当然就是在View树的源头了——ViewRoot!,ViewRoot中包含了窗口的总容器DecorView,ViewRoot中的performTraversal()方法会依次调用decorView的measure、layout、draw方法,从而完成view树的绘制。
 

onAttachedToWindow () 和 onDetachedFromWindow () 
onAttachedToWindow是在第一次onDraw前调用的。也就是我们写的View在没有绘制出来时调用的,但只会调用一次。
onDetachedFromWindow:销毁资源(既销毁view)之后调用。

veiw状态的保持:onSaveInstanceState()方法

invalidate()是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时,调用invalidate()才能

看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。

invalidate()得在UI线程中被调动,在工作者线程中可以通过Handler来通知UI线程进行界面更新。而postInvalidate()在工作者线程中被调用。

Android View刷新机制

        由ViewRoot对象的performTraversals()方法调用draw()方法发起绘制该View树,值得注意的是每次发起绘图时,并不会重新绘制每个View树的视图,而只会重新绘制那些“需要重绘”的视图,View类内部变量包含了一个标志位DRAWN,当该视图需要重绘时,就会为该View添加该标志位。

        调用流程 : 

        mView.draw()开始绘制,draw()方法实现的功能如下:

        绘制该View的背景

        为显示渐变框做一些准备操作(见5,大多数情况下,不需要改渐变框)          

        调用onDraw()方法绘制视图本身   (每个View都需要重载该方法,ViewGroup不需要实现该方法)

        调用dispatchDraw ()方法绘制子视图(如果该View类型不为ViewGroup,即不包含子视图,不需要重载该方法)值得说明的是,ViewGroup类已经为我们重写了dispatchDraw ()的功能实现,应用程序一般不需要重写该方法,但可以重载父类函数实现具体的功能。

在Android的布局体系中,父View负责刷新、布局显示子View;而当子View需要刷新时,则是通知父View来完成。这种处理逻辑在View的代码中明确的表现出来:

子View调用invalidate时,首先找到自己父View(View的成员变量mParent记录自己的父View),然后将AttachInfo中保存的信息告诉父View刷新自己。
 

参考:https://blog.csdn.net/yanbober/article/details/46128379

https://blog.csdn.net/kc58236582/article/details/52411791

猜你喜欢

转载自blog.csdn.net/kdsde/article/details/84315910