Reputation: 6193
I've got a utility method (below) that resizes a bitmap and gives me back a new version. Since I am doing this with quite a few images & I wanted to reduce the chance of running out of memory, I've recycled the bitmap after usage.
This works fine on almost all devices. However, I've notice on the samsung galaxy tab 3 (10 inch) and the note 10.1 (2014) I'm getting the below stack traces:
java.lang.IllegalArgumentException: Cannot draw recycled bitmaps
at android.view.GLES20Canvas.drawBitmap(GLES20Canvas.java:756)
at android.view.GLES20RecordingCanvas.drawBitmap(GLES20RecordingCanvas.java:104)
Below is my resize code:
private static Bitmap resizeBitmap(int newWidth, int newHeight, Bitmap bitmapResize) {
if (bitmapResize == null) {
return null;
}
int width = bitmapResize.getWidth();
int height = bitmapResize.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmapResize,
newWidth, newHeight, true);
//SHOULD I DO THIS???
bitmapResize.recycle();
return resizedBitmap;
}
I have not figured out why almost all devices work, except those 2 (there may be more). The emulator shows no issues either.
It might be worth noting, not all images give me a "Cannot draw recycled bitmaps" error. Only some. But its consistently the same images.
(In case its of use, my app runs on 2.2 upwards)
Upvotes: 2
Views: 1112
Reputation: 6193
I've managed to find the solution to my issue. It turns out the original image may be passed back as an optimisation, if the width/height of the resize match the original image.
I imagine on some devices my computations resulted in me trying to resize an image to its existing size. When i recycled the "old" bitmap, i was recyling the resized one too.
The solution is to change my code to say
if (bitmapResize!=resizedBitmap )
bitmapResize.recycle();
I found my issue covered in this conversation ( which i didn't find in my initial searching for the issue)
https://groups.google.com/forum/#!topic/android-developers/M6njPbo3U0c
Upvotes: 5
Reputation: 1662
You may simply use input bitmap reference as output. This way your input bitmap will be overwritten and you won't need to recycle it.
Kind of:
private static Bitmap resizeBitmap(int newWidth, int newHeight, Bitmap bitmapResize) {
if (bitmapResize == null) {
return null;
}
int width = bitmapResize.getWidth();
int height = bitmapResize.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
return Bitmap.createScaledBitmap(bitmapResize,
newWidth, newHeight, true);
}
Upvotes: 0
Reputation: 1409
I had a similar issue with on of ma games and from my experience you are doing the right thing. its the right place to recycle the old bitmap and will prevent OutOfMemoryExceptions, keep in mind that this instance of Bitmap will not be usable anymore.
Upvotes: 0