View框架之measure()流程

本文详细探讨了Android中View的measure()流程,从MesureSpec的介绍开始,逐步剖析了DecorView和一般View的MesureSpec计算过程,并深入讲解了ViewGroup的measure()操作。文中还强调了如何通过保存MesureSpec值来优化性能,避免不必要的onMeasure()调用。
摘要由CSDN通过智能技术生成

先来张View体系中measure()流程的时序图

注意:1.以下MeasureSpec用ms来代替(ms具体会在后面介绍)
     2.该时序图描述的是从ViewRootImpl开始的measure()过程,因为ViewRootImpl是window与view连接的枢纽
     3.该时序图着重于大概流程及重要方法的作用,具体代码细节会放到后面介绍
     4.DecorView作为顶级View,本身是一个frameLayout,所以也是一个ViewGroup

这里写图片描述

MesureSpec简介 (以下简称ms)

在view的测量过程中,ms起着非常重要的作用,ms在某种程度上来说更像是一种测量的标准。

ms是一个32位的int值,前2位代表测量模式,后30位代表测量大小

测量模式(Specmode)一共分为3种:

    UNSPECIFIED: 父容器不对子view限制,这种情况一般我们用不到,系统内部使用

    EXACTLY :  父容器可以算出View的具体的大小,一般对应于 具体值或者match_parent

    AT_MOST : 父容器指定一个值,子view不能超过这个值,一般对应于 wrap_content

View关于MesureSpec的计算

一般情况下,一个view的ms的测量是根据父容器的ms和本身的LayoutParams来决定的,根据一些规则,在父容器中算出ms,然后父容器调用此view的measure()方法将结果传给该view,该view接着会回掉onMeasure()将结果传给该view的实现类。  但是DecorView作为顶级View是没有父容器的,所以DecorView的ms是根据窗口的大小和自身的LayoutParams来决定的。

1.DecorView的ms计算过程:

--


         /**
           *     desireWindowWidth : 代表屏幕的宽带 ,同理,dwh 代表屏幕的高度
          **/
      private boolean measureHierarchy(final View host, final WindowManager.LayoutParams lp,
        final Resources res, final int desiredWindowWidth, final int desiredWindowHeight) {

              *************************省略

           //计算出DecorView的ms
            ** childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);
               childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height); **

             *************************省略
}

    /**
    * 计算出decorView的ms*
    **/
  private static int getRootMeasureSpec(int windowSize, int rootDimension) {
    int measureSpec;
    switch (rootDimension) {
    case ViewGroup.LayoutParams.MATCH_PARENT:
        //如果设置的是math_parent,屏幕长度就是view长度,模式为EXACTLY
        measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);
        break;
    case ViewGroup.LayoutParams.WRAP_CONTENT:
       //如果设置的是wrap_conentt,屏幕长度就是view长度,模式为AT_MOST
        measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);
        break;
    default:
        // 如果设置的是具体的数值,这个值就是View的长度,模式威EXANTLY
        measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);
        break;
    }
    return measureSpec;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值