Android Honeycomb中的Bitmap#recycle()实际上做了什么?

我正在为Android Honeycomb编写一个内存密集的应用程序,并且我一直非常小心地尽可能地recycle()未使用的Bitmap 。 事实上,这对于应用程序来说是必要的,因为Bitmap不断循环进出内存。 但是,我刚刚在Activity实现onConfigurationChanged() ,所以(由于多种原因)我试图把释放内存的例程放在onStop()

目前我的onStop()方法:

  • 设置一些View来显示默认的Drawable ;
  • 调用这些View以前使用的Bitmap上的recycle() ;
  • 空位引用Bitmap

不幸的是,使用Eclipse内存分析器,似乎这完全不影响内存使用情况

你可以想象,为了以名义上的垃圾收集语言释放资源做了很多努力,我希望能有更多的效果。 所以我的问题是: recycle()做什么? 它实际上是否会触发垃圾收集,或者系统是否会保持内存 – 即使您调用System.gc()直到它感觉需要摆脱某些东西?

NB我知道Bitmap实际上并不在常规堆中,但是我认为调用recycle()足以确保它们从本地堆中退出。

答案的一部分

我发现如果一个ImageView包含一个已经被回收BitmapBitmap数据仍然保留在内存中,直到在ImageView上调用setImageBitmap(null) 。 如果调用setImageResource(...)setImageDrawable(...)那么情况甚至可能是这样的(他们是,加载在一个相对较小的9个补丁中 – 但是,MAT分析显示这并没有消除大的Bitmap ,包含在ImageView的私有成员中)。 在onStop()中调用这个函数已经从我们的应用程序的堆中挑出了大约10MB。 不过,显然这可能并不适用于Android之前的Honeycomb版本。

Solutions Collecting From Web of "Android Honeycomb中的Bitmap#recycle()实际上做了什么?"

正如Justin所说,位图数据不会在VM堆中分配。 在VM堆(它很小)中有一个引用,但实际的数据是由底层的Skiagraphics库在Native堆中分配的。 [请注意,在以后的Android版本中,这可能已经发生了变化,但在2.1和2.2版本中是这样的]当您执行一个recycle()时,VM堆中的小部分和本机堆中的实际数据都是可用的, GC。 但实际的收集是由两个不同的GC机制执行的。 VM堆中的部分由Davlik GC收集 – 您可以通过DDMS看到。 但是本地堆数据是由Skia GC收集的,似乎比较懒惰(运行频率较低?)。 这意味着,即使使用严格的循环(),也有可能领先本地堆GC。 幸运的是有机制来监视本地堆的状态。 看到BitmapFactory OOM驱使我坚果 。

我发现,在Honeycomb之后,如果一个ImageView包含一个已经被回收的BitmapBitmap数据仍然保留在内存中,直到在ImageView上调用setImageBitmap(null) 。 如果调用setImageResource(...)setImageDrawable(...)甚至可能会出现这种情况(在这种情况下,一个非常大的位图被一个相当小的九个补丁代替,但只有在调用了setImageBitmap(null)在加载九个补丁之前是实际处理的内存)。

回收释放分配给位图的本机内存。 实际的Bitmap对象将保留在Dalvik Heap中,直到下一个垃圾收集(但是这个对象占用的内存不重要)。

据我所知,真的没有办法转储本地堆。 因此,您将无法查看位图的本机数据是否通过堆转储消失。 但是,您应该看到应用程序正在使用的内存总量已经减less。 这个问题应该可以帮助你发现访问应用程序的内存使用统计信息的各种方法。