标签:patch ondraw 技术 height als com 分析 进阶 艺术
在分析View的工作流程时,需要先分析一个很重要的类,MeasureSpec。这个类在View的测量(Measure)过程中会用到。
MeasureSpec是View的静态内部类,可以理解为是一种测量规格,是一个32位int值,高2位代表SpecMode,低30位代表SpecSize,SpecMode是指测量模式,而SpecSize是指在某种测量模式下的规格大小。
SpecMode有三种模式,分别为:
系统通过MeasureSpec作为测量规格,对View进行测量,但在设置View的宽高时,都是通过LayoutParams,因此系统在测量View的时候,会将LayoutParams在父容器的约束下转换成MeasureSpec,然后根据确定的MeasureSepc得到View测量后的宽高。有几点需要说明:
ViewRoot是连接WindowManager与DecorView的纽带,View的绘制流程都是通过ViewRoot来完成的。
View的工作流程是从ViewRoot的performTraversals方法开始的,它经过measure、layout和draw三个过程才能最终将一个View绘制出来,其中measure用来测量View的宽和高,layout用来确定View在父容器中的放置位置,而draw则负责将View绘制在屏幕上。用一张 大专栏 分析Android中View的工作流程图来描述View的工作过程:
在View的Measure过程中,完成对View的测量,确定View的宽高。ViewRoot中的performTraversals()会依次调用ViewRoot中的performMeasure()、performLayout()和performDraw()三个方法,这三个方法分别完成顶级View的measure、layout和draw这三大流程。其中在performMeasure()中会调用View的measure()方法,在measure()方法中又会调用onMeasure()方法。在onMeasure()中将View宽/高的测量值传给setMeasuredDimension()方法,完成View的测量过程。
对于ViewGroup来说,除了完成自己的measure过程以外,还会遍历去调用所有子元素的measure()方法,各个子元素再递归去执行这个过程。和View不同的是,ViewGroup是一个抽象类,因此它没有重写View的onMeasure方法,因为不同的ViewGroup子类有不同的布局特性,这导致它们的测量细节各不相同。在ViewGroup的onMeasure()中最后也会调用setMeasuredDimension()方法,完成测量过程。
measure完成以后,通过getMeasuredWidth()/Height()方法就可以正确地获取到View的测量宽/高。需要注意的是,在某些极端情况下,系统可能需要多次measure才能确定最终的测量宽/高,在这种情形下,在onMeasure方法中拿到的测量宽/高很可能是不准确的。一个比较好的习惯是在onLayout方法中去获取View的测量宽/高或者最终宽/高。
Layout的作用是ViewGroup用来确定子元素的位置,ViewRoot中的performLayout()中会调用View的layout()方法,在layout()方法中onLayout()方法又会被调用。onLayout的具体实现同样和具体的布局有关,所以View和ViewGroup均没有真正实现onLayout方法。
当ViewGroup的位置被确定后,它在onLayout()中会遍历所有的子元素并调用其layout()方法,layout()方法确定View本身的位置,而onLayout()方法则会确定所有子元素的位置。
Draw的作用是将View绘制到屏幕上面。View的绘制过程遵循如下几步:
View绘制过程的传递是通过dispatchDraw来实现的,dispatchDraw会遍历调用所有子元素的draw方法,如此draw事件就一层层地传递了下去。
[1] 任玉刚.Android开发艺术探索[M].电子工业出版社, 2015.9:1 - 507
本文链接:http://www.sguotao.top/Android进阶-2016-07-07-分析Android中View的绘制流程.html
标签:patch ondraw 技术 height als com 分析 进阶 艺术
原文地址:https://www.cnblogs.com/lijianming180/p/12276056.html