假设我已将图像加载到位图对象中,如
Bitmap myBitmap = BitmapFactory.decodeFile(myFile);
现在,如果我加载另一个像
这样的位图会发生什么myBitmap = BitmapFactory.decodeFile(myFile2);
第一个myBitmap会发生什么?它是否收集垃圾或者我必须在加载另一个位图之前手动垃圾收集它,例如。 myBitmap.recycle()
?
此外,是否有更好的方法来加载大型图像并在途中回收时一个接一个地显示它们?
答案 0 :(得分:69)
解码第二个位图时,第一个位图不是garbage collected。 Garbage Collector稍后会在决定时执行此操作。如果你想尽快释放内存,你应该在解码第二个位图之前调用recycle()
。
如果要加载非常大的图像,则应重新采样。这是一个例子:Strange out of memory issue while loading an image to a Bitmap object。
答案 1 :(得分:21)
在加载下一张图片之前,您需要调用myBitmap.recycle()。
取决于myFile的来源(例如,如果它是您无法控制原始大小的东西),在加载图像而不是简单地重新采样某些任意数字时,您应该将图像缩放到显示尺寸。 / p>
if (myBitmap != null) {
myBitmap.recycle();
myBitmap = null;
}
Bitmap original = BitmapFactory.decodeFile(myFile);
myBitmap = Bitmap.createScaledBitmap(original, displayWidth, displayHeight, true);
if (original != myBitmap)
original.recycle();
original = null;
我缓存displayWidth& displayHeight in我在Activity的开头初始化的静态。
Display display = getWindowManager().getDefaultDisplay();
displayWidth = display.getWidth();
displayHeight = display.getHeight();
答案 2 :(得分:21)
我认为问题在于:在预蜂窝版本的Android上,实际的原始位图数据不会存储在VM内存中,而是存储在本机内存中。当相应的java Bitmap
对象是GC时,将释放此本机内存 。
然而,当你的本机内存不足时,dalvik GC不会被触发,所以你的应用程序可能只使用了很少的java内存,因此dalvik GC永远不会被调用但它使用大量本机内存来制作位图,最终导致OOM错误。
至少这是我的猜测。值得庆幸的是,在Honeycomb及之后,所有位图数据都存储在VM中,因此您根本不必使用recycle()
。但对于数以百万计的2.3用户(碎片摇动拳头),你应尽可能使用recycle()
(大麻烦)。或者,您也可以调用GC。
答案 3 :(得分:10)
一旦位图已加载到内存中,实际上它是由两部分数据构成的。 第一部分包括有关位图的一些信息,另一部分包括有关位图像素的信息(它由字节数组构成)。 第一部分存在于Java使用的内存中,第二部分存在于C ++使用的内存中。它可以直接使用彼此的内存。 Bitmap.recycle()用于释放C ++的内存。 如果你只这样做,GC将收集java的一部分,并且总是使用C的内存。
答案 4 :(得分:8)
根据: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
此外,在Android 3.0(API Level 11)之前,位图的后备数据存储在本机内存中,而该内存未以可预测的方式发布,可能导致应用程序短暂超出其内存限制崩溃。