Android 为什么即使未引用视图,位图也不会被销毁?

Android 为什么即使未引用视图,位图也不会被销毁?,android,memory-leaks,bitmap,garbage-collection,Android,Memory Leaks,Bitmap,Garbage Collection,在我的片段中有一个扩展线性布局的自定义视图。让我们称之为gallery @Override protected void onDetachedFromWindow() { super.onDestroyView(); imageView1 = null; ... imageView5 = null; } 在该自定义视图中,我有5个ImageView。每个包含一个从web加载的图像 当不再需要我的片段时,我将销毁onDestroyView()中的引用 我注意到,我

在我的
片段中
有一个扩展
线性布局的自定义视图
。让我们称之为
gallery

@Override
protected void onDetachedFromWindow() {
    super.onDestroyView();
    imageView1 = null;
    ...
    imageView5 = null;
}
在该自定义视图中,我有5个
ImageView
。每个包含一个从web加载的图像

当不再需要我的
片段时,我将销毁
onDestroyView()中的引用

我注意到,我的应用程序内存泄漏,使用DDMS和MAT,我发现
ImageView
s中的5个
Bitmap
仍在内存中。那不好。所以在下一步,我在我的
迷你图库中做了这件事

@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;
}
这很有帮助。内存被释放,内存泄漏被堵塞

现在我的问题是——为什么?为什么,当我的图库没有被任何东西引用时,它就没有被引用?更重要的是,当
ImageView
没有引用时,它的内容-位图-从来没有
GC
?我应该强制清理图像位图吗


我注意到,在使用
ImageView
的其他自定义视图中,我也遇到了类似的问题。这种情况下的最佳实践是什么?

需要时将调用GC。就像操作系统内存不足一样,它会调用gc。。然后gc将检查所有未引用的对象并清除它们


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

我们都知道,调用GC的时间是不确定的,@Farhan正确地说,调用system.GC()也不能保证对象将被垃圾收集,我们不能真正依赖它。也不建议自己做清理工作

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

公共空间回收()

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

即使很难,也有人说它应该被称为而不是。注意到的重要一行是释放与此位图关联的本机对象,并清除对像素数据的引用。这将不会同步释放像素数据;它只允许在没有其他引用的情况下对位图进行垃圾收集。这表示调用此方法将使位图被垃圾收集

在这方面我进行了更多的研究,发现许多人对同一问题进行了长时间的讨论


在讨论中,我发现了Sandeep Choudhary发布的一个解决方案,他使用Bitmap.recycle()提供了一个关于细节的小解决方案。

由于这个自定义视图,我收到了OOM错误。。。当我在片段中删除对
gallery
的引用时,我会说这是真的。但当我删除对每个
图像视图的引用时
。。。在6次片段访问之后,我记忆中有30个图像视图。通过DDMS强制GC没有任何作用。calling system.GC()也不会强制它调用,它只是通知系统“现在可能是调用GC的正确时间”。。类似的东西..你是如何制作位图的?您可能希望共享更多关于该自定义视图的代码。我的自定义视图没有什么特别之处。它充当图像视图的容器,并提取到单独的视图以实现重用。位图是由
UniversalImageLoader
库创建的。您是如何销毁该
视图的?我的意思是,你如何调用/做才能确保你的
onDestroyView()
方法被调用?它是片段生命周期的一部分。没错,我的意思是
onDestroyView()
只有在调用
finish()
方法时才会被调用。这并不能保证调用您的
onDestroyView()
,泄漏可能就在这里。顺便说一下,在您的
onDetachFromWindow()
方法中,您只需调用
super.onDestroyView()
,就不会调用自定义实现。你可能想看看这个