详解MeasureSpec

定义:

MeasureSpec是Android view测量系统的重要的一元,它是一个32位的int值,高两位代表测量模式SpecMode,低30位代表测量的大小SpecSize,MeasureSpec用一个int值同时存放了两个信息,而且还节省了内存的开销。

分析目的

本篇文章不分析MeasureSpec在Android 测量系统中的具体作用,只分析它这种节省内存的设计源码的实现。

开始

首先贴一下MesureSpec的源码实现,删除了一部分,主要源码如下:

 public static class MeasureSpec {
        private static final int MODE_SHIFT = 30;
        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
        //下面三个常量是测量模式
        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
        public static final int EXACTLY     = 1 << MODE_SHIFT;
        public static final int AT_MOST     = 2 << MODE_SHIFT;
        //制作一个mesurespec
        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
                                          @MeasureSpecMode int mode) 
                return (size & ~MODE_MASK) | (mode & MODE_MASK);
            }
        }
      //获取测量墨水,也就是高两位
        public static int getMode(int measureSpec) {
            //noinspection ResourceType
            return (measureSpec & MODE_MASK);
        }
       //获取测量大小,也就是低30位
        public static int getSize(int measureSpec) {
            return (measureSpec & ~MODE_MASK);
        }
    }

首先我们回顾一下java中运算符:


详解MeasureSpec_第1张图片
屏幕快照 2019-05-28 上午11.34.21.png

ModeMask

第一个常量ModeMask是3向左位移了30位,因为int型以四个字节存储,所以3的二进制在内存中存储:
00000000 00000000 00000000 00000011
左位移30位之后:
11000000 00000000 00000000 00000000

EXACTLY

EXACTLY常量1在内存中存储:
00000000 00000000 00000000 00000001
左位移30位之后:
01000000 00000000 00000000 00000000

AT_MOST

AT_MOST常量2在内存存储:
00000000 00000000 00000000 00000010
左位移30位之后:
10000000 00000000 00000000 00000000

合成int值

例如makeMeasureSpec传入的参数mode是EXACTLY,size是8
(size & ~MODE_MASK) | (mode & MODE_MASK)
执行上面的表达式
~MODE_MASK :
00111111 11111111 11111111 11111111
size:
00000000 0000000 00000000 00001000
size & ~MODE_MASK:
00000000 00000000 00000000 00001000
EXACTLY:
01000000 00000000 00000000 00000000
mode & MODE_MASK:
01000000 00000000 00000000 00000000
最后(size & ~MODE_MASK) | (mode & MODE_MASK):
00000000 00000000 00000000 00001000
|
01000000 00000000 00000000 00000000
=
01000000 00000000 00000000 00001000
最终 measureSpec的值是这样。

getMode()方法:measureSpec & MODE_MASK)

01000000 00000000 00000000 00001000 // measureSpec
&
11000000 00000000 00000000 00000000 // MODE_MASK
=
01000000 00000000 00000000 00000000
正好就是当时合成EXACTLY的值。

getSize(): (measureSpec & ~MODE_MASK);

01000000 00000000 00000000 00001000 // measureSpec
&
00111111 11111111 11111111 11111111 // MODE_MASK
=
00000000 00000000 00000000 00001000
最终我们获取到的size就是合成时候的8.

注:文章图片来源是https://blog.csdn.net/MoreWindows/article/details/7354571

你可能感兴趣的:(详解MeasureSpec)