Android Bitmap内存泄漏

时间:2013-06-10 00:09:40

标签: android bitmap

我正在尝试为Android创建缓存图像系统,但内存消耗只会增长和增长。我查看了Android website的一些想法,但这个问题并不想消失。

以下是我从SD卡获取图像,设置并稍后销毁的代码。 我做错了什么?

WeakReference<Bitmap> newImageRef;
    public void setImageFromFile(File source){
        if(source.exists()){

            Bitmap newImage = BitmapFactory.decodeFile(source.getAbsolutePath());
            newImageRef =   new WeakReference<Bitmap>(newImage);
            if(newImage != null){
                this.setImageBitmap(newImage);
            }
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        Bitmap newImage = newImageRef.get();
        if (newImage != null) {
        newImage.recycle();
        newImage = null;
        }


        Drawable drawable = getDrawable();
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            Bitmap bitmap = bitmapDrawable.getBitmap();
            if (bitmap != null){
            bitmap.recycle();
            }
        }
        this.setImageResource(0);
        newImage = null;
        newImageRef = null;
        System.gc();


        super.onDetachedFromWindow();
    }

3 个答案:

答案 0 :(得分:2)

如果您使用的是Android版本&gt; 3.0,则无需调用recycle(),因为只要没有对它的引用,gc就会自行清理位图。因此,删除回收电话是安全的。他们在这里什么都不做。

您发布的代码看起来很整洁但是您确定泄漏不会发生在其他地方。使用Android Memory Analyzer工具查看泄漏发生的位置,然后发布信息。

祝你好运。

答案 1 :(得分:1)

尝试使用Drawable.setCallback(null);。在Android 3.0或更高版本中,由于比早期版本更多的自动内存管理或垃圾收集,您甚至不需要recycle。另见this。它具有关于Android中位图内存管理的良好信息。

答案 2 :(得分:0)

在此代码中,很难检查是否存在详细的错误,因为这似乎是“完全缓存”的简化版本。至少你提供的几行似乎没问题。

主要问题是在处理Bitmaps时GC似乎有点奇怪。如果您只是删除硬引用,它有时会挂在Bitmaps上一段时间,可能是因为Bitmap对象的分配方式。如前所述,在Android 3+上不需要回收。因此,如果要添加大量的位图,可能需要一些时间才能再次释放此内存。或者内存泄漏可能是代码的另一部分。对于复杂的问题,例如在重新实施之前检查已经过验证的解决方案是明智的。

这让我想到了第二个问题:使用弱引用。这可能不是针对主要问题,但通常不是用于android doc所写的Android 2.3+中的图像缓存的好模式:

  

注意:过去,流行的内存缓存实现是SoftReference或WeakReference位图缓存,但不建议这样做。从Android 2.3(API级别9)开始,垃圾收集器更积极地收集软/弱引用,这使得它们相当无效。此外,在Android 3.0(API Level 11)之前,位图的后备数据存储在本机内存中,而该内存未以可预测的方式发布,可能导致应用程序短暂超出其内存限制并崩溃。

现在的方法是使用LRU缓存,这在caching提供的链接中有详细解释。