位图大小超过VM预算,不了解原因

时间:2011-06-13 23:37:42

标签: android memory bitmap memory-leaks

我一直在寻找“位图大小超过VM预算”的问题,但这些解决方案似乎都不适用于我。我不明白为什么我的程序有时会抛出这个错误,因为我使用它的方式似乎不会导致任何可能的内存泄漏。我的堆栈跟踪指向BitmapFactory.decodeResource()方法。我有一张背景图片,我用它在画布上绘图,这就是我初始化它的方式:

Bitmap backgroundImage = BitmapFactory.decodeResource(getResources(),
    R.drawable.background);
backgroundImage = resizeImage(backgroundImage, w, h);

这就是我一直在使用它的方式:

canvas.drawBitmap(backgroundImage, 0, 0, paint);

我认为将backgroundImage = null置于onDestroy方法会有所帮助,但这没有做任何事情。除了XML文件之外,我的程序中没有对背景图像资源的其他引用,但我认为这不会影响它。有人可以向我解释为什么会发生这种情况以及如何解决这个问题吗?

顺便说一下,此应用中没有涉及屏幕方向更改。

1 个答案:

答案 0 :(得分:3)

完成后,您需要释放位图像素。您提到您将其值设置为null,但这只会使GC 符合条件,它没有明确告诉VM您已完成这些像素,现在是是释放它们的好时机。

在将其设置为null之前,只需在位图上调用Bitmap#recycle()

protected void onDestroy() {
    if (this.backgroundImage != null) {
        this.backgroundImage.recycle();
        this.backgroundImage = null;
    }
}

此外,您可能在resizeImage()方法中浪费了资源,而您没有提供代码。在解码时对Bitmap进行适当的下采样效率更高,而不是加载全尺寸Bitmap,然后从那里缩小它。

一般的技巧是使用3-argument version的BitmapFactory.decodeResource()和BitmapFactory.Options#inJustDecodeBounds进行第一次传递,以获得Bitmap的宽度/高度(尽管在你的例如,因为它来自应用程序的资源,所以你没有理由甚至不得不这样做......但无论如何我都会解释它;然后根据目标大小确定合适的samplesize,并再次解码位图。这通常会导致更少的内存使用,特别是对于非常大的图像(例如,inSampleSize设置为2,它会解码全尺寸的Bitmap,但只为原始大小的一半的Bitmap分配足够的内存,缩小过程中的位图)。