理解MeasureSpec
1.左移和右移
java中的移位运算符有三种:
-
左移<<
左移就是将左边的操作数在内存中的二进制数据左移指定的位数,左边移空的部分补零。num << n, 相当于 num 乘以2的 n 次方 -
右移>>
右移:右边超出截掉,左边补上符号位 (负的就填1 正的就填0)。num >> n, 相当于 num 除以2的 n 次方
- 无符号右移>>>
无符号右移无论最高位是什么,空位都补零
2.MeasureSpec构成
public static int makeMeasureSpec( int size, int mode) {
if (sUseBrokenMakeMeasureSpec) {
return size + mode;
} else {
return (size & ~MODE_MASK) | (mode & MODE_MASK);
}
}
}
MeasureSpec其实就是一个32位的int类型值(4个字节32bit),由高2位的mode和低30位的size组成
3.getMode
MeasureSpec有三种mode。UNSPECIFIED , EXACTLY , AT_MOST
private static final int MODE_SHIFT = 30;
private static final int MODE_MASK = 0x3 << MODE_SHIFT;
/**
* Measure specification mode: The parent has not imposed any constraint
* on the child. It can be whatever size it wants.
*/
public static final int UNSPECIFIED = 0 << MODE_SHIFT;
/**
* Measure specification mode: The parent has determined an exact size
* for the child. The child is going to be given those bounds regardless
* of how big it wants to be.
*/
public static final int EXACTLY = 1 << MODE_SHIFT;
/**
* Measure specification mode: The child can be as large as it wants up
* to the specified size.
*/
public static final int AT_MOST = 2 << MODE_SHIFT;
- UNSPECIFIED = 0 << MODE_SHIFT; 即: 00000000 00000000 00000000 00000000
- EXACTLY = 1 << MODE_SHIFT; 即: 01000000 00000000 00000000 00000000
- AT_MOST = 2 << MODE_SHIFT; 即: 10000000 00000000 00000000 00000000
public static int getMode(int measureSpec) {
//noinspection ResourceType
return (measureSpec & MODE_MASK);
}
getMode()方法中,MODE_MASK=11000000 00000000 00000000 00000000,将32位的measureSpec和11000000 00000000 00000000 00000000进行&运算,最终得到的肯定是measureSpec的高2位。
比如生成measureSpec时传入AT_MOST。那么measureSpec为10000000 00000000 00000000 00000101,
measureSpec & MODE_MASK 即
10000000 00000000 00000000 00000101
&
11000000 00000000 00000000 00000000
=
10000000 00000000 00000000 00000000
=AT_MOST
传入measureSpec后,measureSpec的低30位肯定全部为0,最终只剩下高2位。而measureSpec的高2位正好就是mode
4.getSize
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
getSize方法原理跟getMode一样,只是先将MODE_MASK取反,
~MODE_MASK=00111111 11111111 11111111 11111111
然后measureSpec和~MODE_MASK进行&运算,结果肯定为measureSpec的低30位了,因为高2位和00进行&运算肯定是00了
5.总结
自定义View时会经常使用到MeasureSpec,通过它拿size或者mode,其实只是生成一个32位的int值,取其高2位或者低30位。提高了运行效率