2012-01-25 132 views
13

我见过很多样本,开发人员在位图上调用recycle(),然后将其设置为null。 为什么这是必要的,不是垃圾收集器照顾释放位图?Android - 位图和内存管理?

Bitmap bitmap = BitmapFactory.decodeStream(inputStream); 
bitmap.recycle(); 
bitmap = null; 

回答

17

加入俱乐部。它有点但不完全。

问题是,在Android的前Honeycomb版本中,位图的内存是从非托管内存分配的,这会产生各种各样的问题。它仍然是从位图对象实现的终结器发布的。这意味着至少需要2次GC通过才能收集。此外,如果因为某种原因终结者未能执行 - 你得到了图片。另一件事是 - 这是真的无从考证 - DDMS不会看到它,同样没有MAT

对于Android 3.0的这个已经改变,位图是在管理字节数组实现,但对于上了年纪的手机...

3

bitmap.recycle();释放位图中使用的本地堆。将其设置为空即可帮助GC快速收集参考。

+3

@aryaxt:请注意,尽管终结器会为您执行一个“recycle()”,但您自己调用它可以更快地释放内存,从而使您不太可能用完堆空间。 – CommonsWare

+1

是....还有一点需要注意....您需要确保在回收之前不再使用位图...否则在尝试使用回收位图时会遇到异常。 –

+4

同样,Android 3.0位图不再使用本机堆。 –

1

来自http://developer.android.com/reference/android/graphics/Bitmap.html#recycle%28%29的文档。


释放与此位图关联的本地对象,并清除对像素数据的引用。这不会同步释放像素数据;它只是允许它被垃圾收集,如果没有其他引用。位图被标记为“死亡”,这意味着如果getPixels()或setPixels()被调用,它将抛出异常,并且不会画任何东西。这个操作不能颠倒过来,所以只有在你确定没有进一步的位图使用时才应该调用它。这是一个高级调用,通常不需要调用,因为当没有更多的位图引用时,普通的GC进程将释放该内存。


所以它似乎没有必要打电话。唯一一次我听说过需要手动将对象设置为null的情况是,如果它的静态变量(或者某个不会轻易超出范围的变量),并且您想强制将其从内存中移出。也许如果你不断快速分配位图,可能需要尝试并强制垃圾收集,但在大多数情况下可能不需要。

+1

根据文档所有内容看起来都不错,但是在位图导致OOM的情况下有很多情况....所以如果你在你的代码中遇到这个问题,修复它的一般方法是确保我们将位图设置为null并从代码中调用gc ...(是的,我知道这不是最优的,它不能保证gc)...但这是获得一些回忆的最后手段....你也可以尝试使用SoftReferences进行位图缓存 –

+0

我已经将数百个位图一次加载到内存中,并没有出现问题。我可以看到这一点的唯一方法是在现代手机上存在的一个问题是,如果您的内存泄露了您的位图,或者您正在快速分配并丢弃位图(远远超过您可以立即安装在屏幕上)。 – onit

+0

http://code.google.com/p/android/issues/detail?id=11089检查罗曼家伙的回应.... –