I've looked all over for "Bitmap size exceeds VM budget" problems, but none of the solutions seem applicable for me. I am not understanding why my program sometimes throws this error because they way I'm using it doesn't seem to cause any possible memory leaks. My stack traces are pointing to the BitmapFactory.decodeResource() method. I've got a background image that I'm using to draw on a Canvas and this is how I've been initializing it:
Bitmap backgroundImage = BitmapFactory.decodeResource(getResources(),
R.drawable.background);
backgroundImage = resizeImage(backgroundImage, w, h);
This is how I've been using it:
canvas.drawBitmap(backgroundImage, 0, 0, paint);
I thought that putting backgroundImage = null
in the onDestroy method would help, but that did nothing. There is not o开发者_如何学Pythonther reference to the background image resource in my program except in an XML file, but I don't think that affects it. Could someone explain to me why this is happening and how to fix it?
By the way, there is not screen orientation changes involved in this app.
You need to free the bitmap pixels when you're done with it. You mentioned that you set its value to null
, but that only makes it eligible for GC, it does not explicitly tell the VM that you're done with those pixels, and that now is a good time to free them.
Before you set it to null, simply call Bitmap#recycle() on the Bitmap:
protected void onDestroy() {
if (this.backgroundImage != null) {
this.backgroundImage.recycle();
this.backgroundImage = null;
}
}
Additionally, you may be wasting resources in your resizeImage()
method, which you did not provide code for. It's much more efficient to do proper down-sampling of the Bitmap at decode-time, rather than loading the full-size Bitmap, and then scaling it down from there.
The general technique is to use the 3-argument version of BitmapFactory.decodeResource(), with BitmapFactory.Options#inJustDecodeBounds for a first-time-pass in order to get the width/height of the Bitmap (although in your case, since it comes from the app's resources, there's no reason you should even have to do that.. but I'll explain it anyway); then determine a proper samplesize based on the target size, and decode the bitmap a second time. That usually results in much less memory usage, especially for very large images (e.g., with inSampleSize
set to 2, it decodes the full-size Bitmap, but only allocates enough memory for a Bitmap of half the original size, downscaling the Bitmap in the process).
精彩评论