定义:
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中运算符:
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