理解MeasureSpec
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位。提高了執行效率