Android MeasureSpec完全解析——手把手教你分析
来源:互联网 发布:win10 1709 知乎 编辑:程序博客网 时间:2024/06/06 16:36
首先把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;
上面的是定义了一些常亮,最后3个我们非常熟悉,就是我们常用的3种测量模式。前两个是做变换用的两个常亮,后面分析会提到这两个常亮的作用。
我们常用的两个方法:
// 将size和mode合成一个32位的int值 public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode) { if (sUseBrokenMakeMeasureSpec) { return size + mode; } else { return (size & ~MODE_MASK) | (mode & MODE_MASK); } } // 拆解出来mode public static int getMode(int measureSpec) { return (measureSpec & MODE_MASK); } // 拆解出来size public static int getSize(int measureSpec) { return (measureSpec & ~MODE_MASK); }
先看makeMeasureSpec
方法,这是将一个size和一个mode组合成一个int值,方法的实现中有一个判断sUseBrokenMakeMeasureSpec
值得操作,这个值是什么呢,源码是这样写的:
/** * Use the old (broken) way of building MeasureSpecs. */ private static boolean sUseBrokenMakeMeasureSpec = false; // 在View的构造函数中sUseBrokenMakeMeasureSpec是这样初始化的 sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
假设我们的size的值是10,用二进制表示则是: 0000 0000 0000 0000 0000 0000 0000 1010
我们用的mode是EXACTLY
,二进制表示是: 0100 0000 0000 0000 0000 0000 0000 0000
1 我们先分析sUseBrokenMakeMeasureSpec == false
的情况,也就是当前系统版本大于JELLY_BEAN_MR1
:
这时返回值是return (size & ~MODE_MASK) | (mode & MODE_MASK)
这个东西具体怎么计算的呢?
在java中,int在内存中占用32位的长度,结合前面的定义: MODE_SHIFT = 30
MODE_MASK = 0x3 << MODE_SHIFT;
0X3用二进制数表示是 0000 0000 0000 0000 0000 0000 0000 0011
,左移30位之后变成了 1100 0000 0000 0000 0000 0000 0000 0000
这是MODE_MASK
的值
那么~MODE_MASK
的值是按位取反后变成了: 0011 1111 1111 1111 1111 1111 1111 1111
size & ~MODE_MASK
按位与的值是: 0000 0000 0000 0000 0000 0000 0000 1010
。
同理我们可以计算出(mode & MODE_MASK)
的值是: 0100 0000 0000 0000 0000 0000 0000 0000
(size & ~MODE_MASK) | (mode & MODE_MASK)
的值是: 0100 0000 0000 0000 0000 0000 0000 1010
2 我们在分析sUseBrokenMakeMeasureSpec == true
的情况:
这时方法返回的是size + mode
,mode转化为10进制的值是1073741824,加上我们的size(10)是1073741834,转为二进制是: 0100 0000 0000 0000 0000 0000 0000 1010
可以看出和我们上面分析的结果是一样的,上面的方式其实就是在求和。至于为什么会分成两种情况,目前我也不清楚,有高手知道可以留言。
下面分析getMode
方法,返回值是measureSpec & MODE_MASK
,我们上面计算的结果是: 0100 0000 0000 0000 0000 0000 0000 1010
MODE_MASK
是 1100 0000 0000 0000 0000 0000 0000 0000
按位与后是 0100 0000 0000 0000 0000 0000 0000 0000
,就是我们的mode。
同理可以分析getSize
方法,返回值是measureSpec & ~MODE_MASK
,是 0100 0000 0000 0000 0000 0000 0000 1010
与 0011 1111 1111 1111 1111 1111 1111 1111
按位与
得到的就是 0000 0000 0000 0000 0000 0000 0000 1010
,就是10的二进制表示方式
以上就是全部内容,总体没有什么大的难度,就是位运算,位运算明白了就透彻了。
- Android MeasureSpec完全解析——手把手教你分析
- Android源码分析之---View.MeasureSpec 解析
- 手把手教你逆向分析 Android 程序
- 手把手教你逆向分析 Android 程序
- 手把手教你逆向分析android程序
- 手把手教你逆向分析 Android 程序
- 手把手教你逆向分析 Android 程序
- 手把手教你解析AXML
- 【Bugly干货分享】手把手教你逆向分析 Android 程序
- 【Bugly干货分享】手把手教你逆向分析 Android 程序
- 【Bugly干货分享】手把手教你逆向分析 Android 程序
- android手把手教你开发launcher——设置壁纸
- 手把手系列之十七——手把手教你做蛋挞
- 手把手系列之三十四——手把手教你做蛋饺
- 手把手系列之四十——手把手教你做双皮奶
- 手把手系列之四十八—手把手教你做寿司
- 手把手教你解析Resources.arsc
- 手把手教你配置Hbase完全分布式环境
- scrapy使用总结
- 【maven】5、Maven 多环境部署(filters、resources、profiles)
- redis介绍和安装
- 配置butterknife8.0
- [舰队收藏]舰娘命名学
- Android MeasureSpec完全解析——手把手教你分析
- bmp2yuv
- 初学分享,求指教
- EXTjs 在IE10下显示不全问题
- 欢迎使用CSDN-markdown编辑器
- centos 6.7 升级opensh7.3
- 宏定义
- C# 网络编程之网页自动登录 (一).使用WebBrower控件模仿登录
- java用jni调用 dll动态库Can't find dependent libraries错误的解决