【问题标题】:Why Bitmaps are not destroyed even though views are not referenced?为什么即使没有引用视图,位图也不会被破坏?
【发布时间】:2014-02-10 13:26:25
【问题描述】:

在我的Fragment 中,我有一个扩展LinearLayout 的自定义视图。我们就叫它gallery

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

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

@Override
public void onDestroyView() {
    super.onDestroyView();
    gallery = null;
}

我注意到,我的应用程序泄漏了内存,并且使用 DDMS 和 MAT 我发现那些 ImageViews 中的 5 个 Bitmap 仍在内存中。那不好。所以下一步我在我的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'ed?甚至更多 - 当ImageView 没有引用它的内容 - 位图 - 从来没有GC'ed?我应该强制清理图像位图吗?

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

【问题讨论】:

  • 你是如何破坏View 的?我的意思是,你调用/做什么来确保你的 onDestroyView() 方法被调用?
  • 它是 Fragment 生命周期的一部分。
  • 没错,我的意思是onDestroyView()只有在finish()方法被调用的时候才会被调用。 并不能保证您的onDestroyView() 会被调用,并且可能是泄漏的来源。顺便说一句,在您的onDetachFromWindow() 方法中,您只需调用super.onDestroyView(),您不会调用您的自定义实现。你可能想看看这个stackoverflow.com/questions/6117341/…

标签: android memory-leaks bitmap garbage-collection


【解决方案1】:

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

所以,为了解决这个问题,特别是针对位图,我从 Bitmap 类中找到了这个函数,它说

公共无效回收()

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

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

对此进行更多搜索,我发现很多人都面临着同样的问题,here.

在讨论中,我找到了 Sandeep Choudhary 发布的解决方案,他使用 Bitmap.recycle() here. 提供了一个包含详细信息的小变通方法

【讨论】:

    【解决方案2】:

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

    您只需要确保没有不必要地保留参考。

    【讨论】:

    • 好吧,由于这个自定义视图,我收到了 OOM 错误...当我在片段中删除对 gallery 的引用时,我会说这是真的。但是当我删除了对每一个 ImageView 的引用时,我在 6 次片段访问后内存中有 30 个 ImageView。而通过 DDMS 强制 GC 什么也没做。
    • 调用 system.gc() 也不会强制它调用,它只是通知系统“这可能是调用 gc 的正确时间”......类似的东西......
    • 你是如何制作位图的?您可能想分享更多关于该自定义视图的代码。
    • 我的自定义视图没有什么特别之处。它充当图像视图的容器,并提取到单独的视图以实现可重用性。位图由UniversalImageLoader library 创建。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-06
    • 2022-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    相关资源
    最近更新 更多