2

我正在尝试为 Android 创建缓存图像系统,但内存消耗只会越来越大。我通过 Android网站查看了一些想法,但问题只是不想消失。

下面是我从 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();
    }
4

3 回答 3

2

如果您使用的是 Android 版本 >3.0,则不必调用recycle(),因为 gc 最终会自行清理位图,只要没有对其的引用。所以删除回收调用是安全的。他们在这里什么都不做。

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

祝你好运。

于 2013-06-26T15:35:33.283 回答
1

尝试使用Drawable.setCallback(null);. 在 Android 3.0 或更高版本中,您甚至不需要这样做,recycle因为与早期版本相比,自动内存管理或垃圾收集更多。另请参阅。它有很好的关于 Android 中位图内存管理的信息。

于 2013-06-26T17:27:39.180 回答
0

在这段代码中,很难检查是否存在详细的错误,因为这似乎是“完整缓存”的简化版本。至少您提供的几行看起来还不错。

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

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

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

现在要走的路是使用 LRU 缓存,在提供的关于缓存的链接中有详细说明。

于 2013-06-26T20:59:25.747 回答