Android RelativeLayout.mesure()时出现NullPointerException异常
2017-07-11 10:01
453 查看
先说说怎么发现的这个问题,项目中使用的是百度地图,在搞百度地图的时候,需要在地图上添加Marker(标注覆盖物),自定义一个布局文件,根Layout为RelativeLayout,然后将自定义的布局文件转换成Bitmap,然后转换成BitmapDescriptor(BitmapDescriptor是百度地图的,这里不是重点),之后添加标注,显示在地图上。做完之后运行测试,没有问题,换一个手机测试,也没有问题,再换一个手机,同样没问题。好了,提交代码。原本以为这点小事就做完了,结果同事更新下来代码之后运行,程序崩溃了,竟然崩溃了......崩溃了.......,我立马拿他手机测试了一下,确实是崩溃了,这尼玛也是醉了。看了一下错误日志,竟然是空指针异常
异常信息:
定位到代码:
private BitmapDescriptor changeToBitmap(View view) {
view.setDrawingCacheEnabled(true);
view.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0,
view.getMeasuredWidth(),
view.getMeasuredHeight());
view.buildDrawingCache();
Bitmap cacheBitmap = view.getDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
BitmapDescriptor icon = BitmapDescriptorFactory.fromBitmap(bitmap);
return icon;
} 发现是view.measure这一行报错,在我测试的其他3部手机上都没问题,结果在这个手机上出问题了,当时第一想法就是android版本的问题,看一下版本,我测试过的3部手机版本分别是21、22、23(即5.0.1、5.1、6.0)没有问题,有问题的那部手机API为17(即android4.2版本),怎么会这样呢,难道view.measure方法在不同的版本源码不同???在线看了一下android源码,尼玛,还真有问题。
首先看官方这么一段话:
大概翻译一下就是:
在平台版本17(包含17)或更低,RelativeLayout会受测量错误的影响导致子视图测量不正确,在RelativeLayout的控件使用在含有scrolling的时候,该含有scrolling的控件中计算空间大小,没有使用MeasureSpec mode UNSPECIFIED的布局方式在RelativeLayout。自定义的控件则会尽可能的使用AT_MOST 来替换对齐方式。
这种行为已经保存应用程序设置Android的targetSdkVersion =“17”或以上的清单的使用SDK标签的兼容性。针对SDK 18版或更新版的应用程序将获得正确的行为。
说人话就是RelativeLayout在API17及以下版本使用measure方法是有BUG的,会出现空指针异常,18及以上是没有问题的。
再看一下RelativeLayout的onMeasure源码(既然官方说18(即android4.3)修复了,那就对比之前的看一下有什么不同吧):
左边是18(android4.3),右边是19(android4.4),可以看到,在4.4版本中增加了非空判断,之前版本没有这个。(说到这我又想吐槽了,刚刚官方明明说18就已经解决这个BUG了,为什么在19上才看到这个非空判断,也是无语。。。)
好了,啰啰嗦嗦那么多,总之就是:
RelativeLayout.measure方法在android4.4版本之后没有空指针异常这个BUG,但之前版本会抛出空指针异常。
解决方法:
在RelativeLayout布局外面再嵌套一层FrameLayout或者LinearLayout即可。
相信会有好多像我一样不知道这个坑的猿猿们,希望能帮到你们。
异常信息:
定位到代码:
private BitmapDescriptor changeToBitmap(View view) {
view.setDrawingCacheEnabled(true);
view.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0,
view.getMeasuredWidth(),
view.getMeasuredHeight());
view.buildDrawingCache();
Bitmap cacheBitmap = view.getDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
BitmapDescriptor icon = BitmapDescriptorFactory.fromBitmap(bitmap);
return icon;
} 发现是view.measure这一行报错,在我测试的其他3部手机上都没问题,结果在这个手机上出问题了,当时第一想法就是android版本的问题,看一下版本,我测试过的3部手机版本分别是21、22、23(即5.0.1、5.1、6.0)没有问题,有问题的那部手机API为17(即android4.2版本),怎么会这样呢,难道view.measure方法在不同的版本源码不同???在线看了一下android源码,尼玛,还真有问题。
首先看官方这么一段话:
大概翻译一下就是:
在平台版本17(包含17)或更低,RelativeLayout会受测量错误的影响导致子视图测量不正确,在RelativeLayout的控件使用在含有scrolling的时候,该含有scrolling的控件中计算空间大小,没有使用MeasureSpec mode UNSPECIFIED的布局方式在RelativeLayout。自定义的控件则会尽可能的使用AT_MOST 来替换对齐方式。
这种行为已经保存应用程序设置Android的targetSdkVersion =“17”或以上的清单的使用SDK标签的兼容性。针对SDK 18版或更新版的应用程序将获得正确的行为。
说人话就是RelativeLayout在API17及以下版本使用measure方法是有BUG的,会出现空指针异常,18及以上是没有问题的。
再看一下RelativeLayout的onMeasure源码(既然官方说18(即android4.3)修复了,那就对比之前的看一下有什么不同吧):
左边是18(android4.3),右边是19(android4.4),可以看到,在4.4版本中增加了非空判断,之前版本没有这个。(说到这我又想吐槽了,刚刚官方明明说18就已经解决这个BUG了,为什么在19上才看到这个非空判断,也是无语。。。)
好了,啰啰嗦嗦那么多,总之就是:
RelativeLayout.measure方法在android4.4版本之后没有空指针异常这个BUG,但之前版本会抛出空指针异常。
解决方法:
在RelativeLayout布局外面再嵌套一层FrameLayout或者LinearLayout即可。
相信会有好多像我一样不知道这个坑的猿猿们,希望能帮到你们。
相关文章推荐
- Android兼容性问题 -- RelativeLayout.mesure()出现NullPointerException异常
- Android 4.3(API 18)及以下调用 RelativeLayout.mesure() 时出现 NullPointerException 异常
- android开发中遇到的问题解决之RelativeLayout执行measure(w,h)方法时,出现NullPointerException的异常情况
- Android 关于RelativeLayout.onMeasure出现的NullPointerException错误
- RelativeLayout执行measure(w,h)方法时,出现NullPointerException的异常情况
- RelativeLayout执行measure(w,h)方法时,出现NullPointerException的异常情况
- Android: NullPointerException when using RelativeLayout with measure()
- android在fragment中实现onTouchEvent办法出现的java.lang.NullPointerException
- 在Servlet使用getServletContext()获取ServletContext对象出现java.lang.NullPointerException(空指针)异常的解决办法
- android中调用findViewById时出现:java.lang.NullPointerException
- 【Android】监听PopupWindow上的控件出现nullpointerException
- Android中SharedPreferences出现NullPointerException的解决办法【转】
- ListView遍历每个Item出现NullPointerException的异常(转)
- Android 开发中出现java.lang.NullPointerException
- ListView遍历每个Item出现NullPointerException的异常
- Android中SharedPreferences出现NullPointerException的解决办法
- 运行Eclipse,Android lint出现错误:java.lang.NullPointerException
- 在Servlet使用getServletContext()获取ServletContext对象出现java.lang.NullPointerException(空指针)异常的解决办法
- Android2.3 版本PopupWindow出现NullPointerException错误
- ListView遍历每个Item出现NullPointerException的异常