现在的位置: 首页 > 移动开发 > 正文

****Android中View绘制流程以及invalidate()等相关方法分析

2019年05月19日 移动开发 ⁄ 共 2526字 ⁄ 字号 评论关闭

整个View树的绘图流程是在ViewRoot.java类的performTraversals()函数展开的,该函数做的执行过程可简单概况为根据之前

状态,判断是否需要重新计算视图大小(measure)、是否重新需要安置视图的位置(layout)、以及是否需要重绘(draw),其框架过程如下:     

           

接下来温习一下整个View树的结构,对每个具体View对象的操作,其实就是个递归的实现。

 

                   

本文相关代码下载

免费下载地址在 http://linux.linuxidc.com/

用户名与密码都是www.linuxidc.com

具体下载目录在 /2012年资料/1月/9日/Android中View绘制流程以及invalidate()等相关方法分析/

 

流程一:      mesarue()过程

        主要作用:为整个View树计算实际的大小,即设置实际的高(对应属性:mMeasuredHeight)和宽(对应属性:mMeasureWidth),

    每个View的控件的实际宽高都是由父视图和本身视图决定的。

 

     具体的调用链如下

          ViewRoot根对象地属性mView(其类型一般为ViewGroup类型)调用measure()方法去计算View树的大小,回调View/ViewGroup

  对象的onMeasure()方法,该方法实现的功能如下:    

          1、设置本View视图的最终大小,该功能的实现通过调用setMeasuredDimension()方法去设置实际的高(对应属性:  

                mMeasuredHeight)和宽(对应属性:mMeasureWidth)   ;

           2 、如果该View对象是个ViewGroup类型,需要重写该onMeasure()方法,对其子视图进行遍历的measure()过程。

               2.1  对每个子视图的measure()过程,是通过调用父类ViewGroup.java类里的measureChildWithMargins()方法去实现,

                 该方法内部只是简单地调用了View对象的measure()方法。(由于measureChildWithMargins()方法只是一个过渡层,更简单

                的做法是直接调用View对象的measure()方法)

              

整个measure调用流程就是个树形的递归过程

measure函数原型为 View.java 该函数不能被重载

 
  1.     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {  
  2.             //....   
  3.           
  4.             //回调onMeasure()方法     
  5.             onMeasure(widthMeasureSpec, heightMeasureSpec);  
  6.              
  7.             //more   
  8.     }  

 

为了大家更好的理解,采用“二B程序员”的方式利用伪代码描述该measure流程       

 
  1. // measure()过程  ViewRoot.java   
  2.    // 发起measure()的"发号者"在ViewRoot.java里的performTraversals()方法, mView.measure()   
  3.    private void  performTraversals(){  
  4.     //...   
  5.       
  6.     View mView  ;  
  7.     mView.measure(h,l) ;  
  8.       
  9.     //....   
  10.    }  
  11.   
  12.   //回调View视图里的onMeasure过程   
  13.   private void onMeasure(int height , int width){  
  14.    //设置该view的实际宽(mMeasuredWidth)高(mMeasuredHeight)   
  15.    //1、该方法必须在onMeasure调用,否者报异常。   
  16.    setMeasuredDimension(h , l) ;  
  17.      
  18.    //2、如果该View是ViewGroup类型,则对它的每个子View进行measure()过程   
  19.    int childCount = getChildCount() ;  
  20.      
  21.    for(int i=0 ;i<childCount ;i++){  
  22.        //2.1、获得每个子View对象引用   
  23.        View child = getChildAt(i) ;  
  24.          
  25.        //整个measure()过程就是个递归过程   
  26.        //该方法只是一个过滤器,最后会调用measure()过程 ;或者 measureChild(child , h, i)方法都   
  27.        measureChildWithMargins(child , h, i) ;   
  28.          
  29.        //其实,对于我们自己写的应用来说,最好的办法是去掉框架里的该方法,直接调用view.measure(),如下:   
  30.        //child.measure(h, l)   
  31.    }  
  32.   }  
  33.     
  34.   //该方法具体实现在ViewGroup.java里 。   
  35.   protected  void measureChildWithMargins(View v, int height , int width){  
  36.    v.measure(h,l)     
  37.   } 

linux

抱歉!评论已关闭.