android中关于bitmap造成的OOM内存溢出防止方法

        近段时间总是遇到bitmap内存溢出的问题,其实除了bitmap造成内存泄露外,还有几种其他的吃内存的可能,这在网上都有总结。总的来说有两种表现形式:


        1.长期保持对某个对象或数据的引用,导致java的垃圾回收器不能回收不再使用的内存空间;

        2.正在使用的有效对象占用内存空间大,导致多个有效对象生成时,吃完程序所分配的内存;


网上有内存溢出的一个总结帖子  http://winuxxan.blog.51cto.com/2779763/512179  可以参考。

       在这里仅对bitmap造成的内存溢出总结一下自己的经验,也便于自己记忆和理解。


bitmap造成的内存溢出对于初学者确实很头疼,因为bitmap占用资源大,很容易吃完内存,这也是内存溢出问题里最为常见的问题(当然无限循环生成对象的情况除外。。。),当然这个问题也是相对于其他内存泄露更容易查找和防止泄露的问题。bitmap的内存溢出让初学者感到疑惑的是其自身的回收方法,什么时候使用recycle()方法回收bitmap是重点。针对以上的两种内存泄露表现形式,对bitmap可从两方面避免内存泄露:

1.减小生成的bitmap占用空间;

2.适时回收不再使用的bitmap;


     减小生成的bitmap占用空间

bitmap对象会将图片资源在内存中存储,图片必定会耗用大量内存,为了防止溢出,可以在生成bitmap资源时,减小其占用的内存空间,一般方法为:
1.通过BitmapFactory.decodeStream方法,创建出一个bitmap,该方法从JNI>>nativeDecodeAsset()来完成decode,从而避免java层decode时的内存开销;

2.利用生成图片时的属性设置,来减小生成图片的尺寸。

BitmapFactory.Options options = new BitmapFactory.Options();
                     options.inSampleSize = 2;

通过设置inSampleSize 的值,将图片的长宽定义成原图的1 / inSampleSize;(这个地方还是很疑惑,在生成小尺寸的图片后放入imageview中显示时,图片有可能会进一步放大,此时占用的内存会不会跟着变多,或许放大的机制不一样,不影响原来内存大小)


     适时回收不再使用的bitmap

回收bitmap占用的内存时需要调用recycle()方法,该方法只能在bitmap放弃所有引用的情况下才能回收,否则会报使用已回收的bitmap的错误。然而我们使用bitmap时,大多数时间是创建的局部变量,引用这些bitmap的控件却是全局的,或者说有更长的生命周期,所以回收bitmap要在控件不再引用该资源的情况下调用recycle()方法,这也是经常调用recycle()方法不成功而放弃回收bitmap的原因。简单点说就是:

局部的bitmap被更长生命周期的控件引用,导致在可以调用recycle方法时不能调用,需要调用recycle方法时没办法引用bitmap;

为了解决这一问题,我们可以建立bitmap的索引用于在需要recycle的时候很方便的调用bitmap对象。同时为了避免索引造成的长期引用,可以将索引由强引用转化为弱引用,保证在内存不足时放弃bitmap的索引。代码形式如下:

List<SoftReference<Bitmap>> bitmaps = new ArrayList<SoftReference<Bitmap>>();

在新建bitmap对象的地方加入引用当中,

SoftReference<Bitmap> btm_soft = new SoftReference<Bitmap>(bitmap_tar);
                    if (btm_soft.get() != null)
                    {
                        bitmaps.add(btm_soft);
                    }

这样就可以在合适的时候回收bitmaps列表中的bitmap了,当然如果想回收特定的某一张图片,可以将列表改成如下形式,通过键值对索引对应的bitmap,进而recycle对象:

List<Map<String, SoftReference<Bitmap>>>bitmaps 

= new new ArrayList<Map<String, SoftReference<Bitmap>>>();

回收图片时,可以采用下面的方式:

if(!bmp.isRecycle() ){
         bmp.recycle()   //回收图片所占的内存
         system.gc()  //提醒系统及时回收
}

bitmap对象最终会被某个控件引用,这里有个可以避免因为回收了bitmap造成控件引用出错的方法,

 Drawable drawable = new BitmapDrawable(btm);

然后用控件引用Drawable资源,在这里Drawable资源会以一个容器的形式出现,控件间接引用bitmap对象,此时,及时bitmap对象被回收了,控件也不会报引用错误,不过现实的内容为空,一般显示为一块黑色区域。

一般情况下,bitmap的操作会涉及网络下载和多线程操作,好的代码设计和清晰的逻辑顺序显得很重要。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值