为什么即使没有引用视图也不会破坏位图?

时间:2014-02-10 13:26:26

标签: android memory-leaks bitmap garbage-collection

在我的Fragment我有一个扩展LinearLayout的自定义视图。我们称之为gallery

在该自定义视图中,我有5个ImageView。每个都包含从网络加载的图像。

当我的Fragment不再需要时,我会销毁onDestroyView()

中的引用
@Override
public void onDestroyView() {
    super.onDestroyView();
    gallery = null;
}

我注意到,我的应用程序泄漏内存并使用DDMS和MAT我发现那些Bitmap中的5 ImageView仍在内存中。那不是好事。所以在下一步我在mini gallery

中做了这个
@Override
protected void onDetachedFromWindow() {
    super.onDestroyView();
    imageView1 = null;
    ...
    imageView5 = null;
}

这也没有帮助。在我最后的尝试中,我做了这个

@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    imageView1.setImageBitmap(null);
    imageView1 = null;
    ...
    imageView5.setImageBitmap(null);
    imageView5 = null;
}

这有帮助。内存被释放,内存泄漏被堵塞。

现在我的问题是 - 为什么?为什么,当我的画廊没有被GC'编辑的任何东西引用时?甚至更多 - 当ImageView不是引用它的内容 - 位图 - 从来没有GC'编辑?我应该强行清理图像位图吗?

我注意到在使用ImageView的其他自定义视图中,我遇到了类似的问题。这类案件的最佳做法是什么?

2 个答案:

答案 0 :(得分:2)

众所周知,当调用GC时它不确定并且@Farhan正确地说调用system.gc()也不能保证对象将被垃圾收集,我们不能真正依赖它。也不建议自己清理。

所以,找到解决这个问题的解决方案,特别是对于Bitmaps,我从Bitmap类升级到了这个函数,它说

public void recycle()

在API级别1中添加 释放与此位图关联的本机对象,并清除对像素数据的引用。这不会同步释放像素数据;如果没有其他引用,它只是允许它被垃圾收集。位图标记为“死”,这意味着如果调用getPixels()或setPixels(),它将抛出异常,并且不会绘制任何内容。此操作无法撤消,因此只有在您确定位图没有进一步用途时才应调用此操作。这是一个高级调用,通常不需要调用,因为正常的GC进程将在没有更多对此位图的引用时释放此内存。

甚至很难说它应该被召唤。它注意到的重要部分是释放与此位图关联的本机对象,并清除对像素数据的引用。这不会同步释放像素数据;如果没有其他引用,它只是允许它被垃圾收集。表明调用此方法将使位图垃圾收集。

关于此问题的更多信息我发现了很多关于同一问题的长期讨论,here.

在讨论中我发现了一个由Sandeep Choudhary发布的解决方案,他使用Bitmap.recycle()here.

给出了一个小细节解决方法。

答案 1 :(得分:0)

GC会在有需要时被调用。就像os在内存上运行不足一样,然后它会调用gc ..然后gc将检查所有未引用的对象并清除它们。

您只需要确保,您没有不必要地保留引用。