我一直在寻找“位图大小超过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文件之外,我的程序中没有对背景图像资源的其他引用,但我认为这不会影响它。有人可以向我解释为什么会发生这种情况以及如何解决这个问题吗?
顺便说一下,此应用中没有涉及屏幕方向更改。
答案 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分配足够的内存,缩小过程中的位图)。