Android的bitmap遇到内存溢出
2016-01-12 15:21
281 查看
第一种方法--及时回收bitmap内存:
一般而言,回收bitmap内存可以用到以下代码
if(bitmap != null && !bitmap.isRecycled()){
bitmap.recycle();
bitmap = null;
}
System.gc();
bitmap.recycle()方法用于回收该bitmap所占用的内存,接着将bitmap置空,最后,别忘了用System.gc()调用一下系统的垃圾回收器。
在这里要声明一下,bitmap可以有多个(以为着可以有多个if语句),但System.gc()最好只有一个(所以我将它写在了if语句外),因为System.gc()
每次调用都要将整个内存扫描一遍,因而如果多次调用的话会影响程序运行的速度。为了程序的效率,我将它放在了所有回收语句之后,
这样已经起到了它的效果,还节约的时间。
回收bitmap已经知道了,那么“及时”怎么理解呢?
根据我的实际经验,bitmap发挥作用的地方要么在View里,要么在Activity里(当然肯定有其他区域,但是原理都是类似的),
回收bitmap的地方最好写在这些区域刚刚不使用bitmap了的时刻。
比如说View如果使用了bitmap,就应该在这个View不再绘制了的时候回收,或者是在跳转到的下一个区域的代码中回收;
再比如说SurfaceView,就应该在onSurfaceDestroyed这个方法中回收;
同理,如果Activity使用了bitmap,就可以在onStop或者onDestroy方法中回收......
结合以上的共同点,“及时回收”的原理就是在使用了bitmap的区域结束时或结束后回收。
第二种方法--压缩图片:
这个方法当然很简单了,就是使图片体积大小变小,
可以有两种方式:
一种是使图片质量降低(分辨率不变),
另一种是使图片分辨率降低(分辨率改变)。
总之,使图片大小变小就行了。
实践证明,使图片质量降低(分辨率不变)可以大幅度地减小体积,而且质量的差异肉眼看上去并不明显。
我刚开始使用的就是这两种方法,原理很简单,可是,我的BUG发生虽然没那么频繁了,但是它依然存在!!
后来经过几天的努力与尝试,结合我项目的一些具体情况,我终于解决了这个令人头痛的BUG,但是事实却有点出乎我的意料。
当我使用了上述两种方法BUG依然还没解决的时候,我开始怀疑,bitmap超过8M会报错,可现在我把前前后后的bitmap都回收了,
不可能还有8M了,那为什么还会报错呢?
终于我发现了这个原因:当内存中已经被一些bitmap使用过之后,无论被回收与否,它都会变得特别“敏感”,这个时候,
如果bitmap突然要占用大量的内存,即使和之前已经剩下的内存加起来不到8M,系统也会报错,原因是它变“敏感”了!
我不知道这个用底层原理如何解释比较好,但是我想“敏感”这个词应该可以很形象地进行解释。
于是,为了顺应内存的“敏感性”,我将那个需要同时装载多个大体积bitmap的地方进行了修改,用到了以下方法:
//压缩,用于节省BITMAP内存空间--解决BUG的关键步骤
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 2; //这个的值压缩的倍数(2的整数倍),数值越小,压缩率越小,图片越清晰
//返回原图解码之后的bitmap对象
bitmap = BitmapFactory.decodeResource(Context, ResourcesId, opts);
即先将图片缩小一倍,再将这缩小了一倍的图片作为bitmap存入内存,这样一来,它占用的bitmap内存大大减小。
后来经测试,BUG果然解决了。图片缩小一倍后,顺应了内存的“敏感性”,也就不会再报错了。
一般而言,回收bitmap内存可以用到以下代码
if(bitmap != null && !bitmap.isRecycled()){
bitmap.recycle();
bitmap = null;
}
System.gc();
bitmap.recycle()方法用于回收该bitmap所占用的内存,接着将bitmap置空,最后,别忘了用System.gc()调用一下系统的垃圾回收器。
在这里要声明一下,bitmap可以有多个(以为着可以有多个if语句),但System.gc()最好只有一个(所以我将它写在了if语句外),因为System.gc()
每次调用都要将整个内存扫描一遍,因而如果多次调用的话会影响程序运行的速度。为了程序的效率,我将它放在了所有回收语句之后,
这样已经起到了它的效果,还节约的时间。
回收bitmap已经知道了,那么“及时”怎么理解呢?
根据我的实际经验,bitmap发挥作用的地方要么在View里,要么在Activity里(当然肯定有其他区域,但是原理都是类似的),
回收bitmap的地方最好写在这些区域刚刚不使用bitmap了的时刻。
比如说View如果使用了bitmap,就应该在这个View不再绘制了的时候回收,或者是在跳转到的下一个区域的代码中回收;
再比如说SurfaceView,就应该在onSurfaceDestroyed这个方法中回收;
同理,如果Activity使用了bitmap,就可以在onStop或者onDestroy方法中回收......
结合以上的共同点,“及时回收”的原理就是在使用了bitmap的区域结束时或结束后回收。
第二种方法--压缩图片:
这个方法当然很简单了,就是使图片体积大小变小,
可以有两种方式:
一种是使图片质量降低(分辨率不变),
另一种是使图片分辨率降低(分辨率改变)。
总之,使图片大小变小就行了。
实践证明,使图片质量降低(分辨率不变)可以大幅度地减小体积,而且质量的差异肉眼看上去并不明显。
我刚开始使用的就是这两种方法,原理很简单,可是,我的BUG发生虽然没那么频繁了,但是它依然存在!!
后来经过几天的努力与尝试,结合我项目的一些具体情况,我终于解决了这个令人头痛的BUG,但是事实却有点出乎我的意料。
当我使用了上述两种方法BUG依然还没解决的时候,我开始怀疑,bitmap超过8M会报错,可现在我把前前后后的bitmap都回收了,
不可能还有8M了,那为什么还会报错呢?
终于我发现了这个原因:当内存中已经被一些bitmap使用过之后,无论被回收与否,它都会变得特别“敏感”,这个时候,
如果bitmap突然要占用大量的内存,即使和之前已经剩下的内存加起来不到8M,系统也会报错,原因是它变“敏感”了!
我不知道这个用底层原理如何解释比较好,但是我想“敏感”这个词应该可以很形象地进行解释。
于是,为了顺应内存的“敏感性”,我将那个需要同时装载多个大体积bitmap的地方进行了修改,用到了以下方法:
//压缩,用于节省BITMAP内存空间--解决BUG的关键步骤
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 2; //这个的值压缩的倍数(2的整数倍),数值越小,压缩率越小,图片越清晰
//返回原图解码之后的bitmap对象
bitmap = BitmapFactory.decodeResource(Context, ResourcesId, opts);
即先将图片缩小一倍,再将这缩小了一倍的图片作为bitmap存入内存,这样一来,它占用的bitmap内存大大减小。
后来经测试,BUG果然解决了。图片缩小一倍后,顺应了内存的“敏感性”,也就不会再报错了。
相关文章推荐
- Android greenrobot的EventBus
- android之adapter用法总结
- android服务- Notification创建通知 - startForeground 使用前台服务
- android 中动态添加view
- Android中的so挂钩(hook)之Inline hook
- Android利用shape画虚线
- Android BLE蓝牙4.0开发详解
- android 自定义view(二)
- Android安全研究经验谈
- Android安全研究经验谈
- android中popupwindow的点滴
- 安卓开发之百度地图定位
- Fresco介绍 - 一个新的android图片加载库
- android选择图片拍照详解(裁剪-旋转-压缩)
- Android 判断一个url是否有效
- Android如何在java代码中设置margin
- Android Studio上NDK/JNI开发环境问题
- Android属性动画完全解析(三)-Interpolator和ViewPropertyAnimator的用法
- android studio 运行出现 com.android.ide.common.process.ProcessException
- Android 监听输入法隐藏与显示状态切换