Android上的位图大小超过VM预算错误

时间:2011-08-18 13:27:42

标签: android image memory memory-leaks

我正在从Asset文件夹向数组对象加载100个图像。图片非常小(每个png~20k),我使用这个代码做,并防止内存泄漏&优化表现:

循环:

// create resized bitmap from asset resource
        InputStream istr = assetManager.open(pics[i]);
        Bitmap b = BitmapFactory.decodeStream(istr);
        b = Bitmap.createScaledBitmap(b, 240, 240, true);

其中pics [i]是位于我的Asset文件夹中的文件名列表。

该代码适用于我,但我仍然不时收到用户的错误(我在Developer Console错误中看到它):

java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
at android.graphics.Bitmap.createBitmap(Bitmap.java:435)
at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340)

我能做些什么来改善它吗?或者这是Android的世界,我们永远无法提供完美的应用程序?

3 个答案:

答案 0 :(得分:2)

位图未压缩,因此它们以width * height * 4字节存储。这意味着每个图像使用大约225 KB的内存。 100张图像需要大约22 MB的内存。最小堆大小为16 MB,但设备通常具有24+ MB堆。此堆不仅用于数据,还用于活动,视图等。这意味着您无法加载此大小的100位图。

答案 1 :(得分:2)

当然你可以改进一些东西:不要同时将太多的图片加载到内存中(或减小它们的大小)。有些设备没有太多可用内存。您的设备可能具有比某些客户电话更高的堆限制。因此,当它适合你时它会崩溃(请参阅this video了解一些堆限制[在4:44])。

您可以通过ActivityManager.getMemoryClass()获得可用的堆大小。

要改善这一点,请立即测试您需要的图片(显示哪些图片),哪些不是。仅加载所需的位图并回收您不再需要的位图。

还可以尝试使用BitmapFactory.decodeResource()BitmapFactory.Options.inSampleSize。这允许您直接以较低分辨率加载图像,而无需以完整尺寸加载它们,然后像​​在此处一样调整它们的大小。

答案 2 :(得分:1)

根据经验,您应该需要来显示用户实际可以看到的内容。在记忆中保存任何其他东西(图形)只是锦上添花。这就是为什么具有更高分辨率屏幕的设备将具有更大的堆大小。

例如,在320x480屏幕上,您只需要至少320x480x4 = 614400(600kb)。

考虑到这一概念,您需要考虑是否需要在内存中保留100 Bitmap个。用户是否一次查看100 Bitmap个?在这种情况下,您可以降低图像的质量而不会降低用户体验(屏幕上只有很多像素)。用户是否滚动了100 Bitmap s?然后根据需要动态地转储和加载图像(通过一些缓存来获得平滑度)。

总有一种解决方法。