I'm getting my bitmap like so from XML:
//Get bitmap from drawable
bd = (BitmapDrawable) view.getResources().getDrawable(R.drawable.backgrounds);
backgrounds = bd.getBitmap();
//Do required work with bitmap (Will just use a log statement here for testing
Log.v("NewTag","Testing: "+bd.getBitmap().getPixel(0, 0));
//Now recycle this large bitmap
bd.getBitmap.recycle();
bd=null;
backgrounds.recycle();
backgrounds=null;
The first time I run this code, all is good. However when I exit my app (using the back key), then restart the app, it may or may not work. Sometimes, I get an error:
Can't call getPixel() on a recycled bitmap
Why? I've not even recycled it yet. Or more accurately, it seems to not be recreating the bitmap and remembering the recycle from last time.
This problem doesn't happen if I use BitmapFactory to obtain the bitmap (unfortunately, I can't do that as I have to get this particular bitmap from an XML alias).
Also prior to installing Lollipop, this worked OK (as long as I had bd = null).
I've been at this problem for 2 days straight so if anyone could throw any light on it I'd be very grateful.
Edit
I've attempted @aga's suggestion of simply not recycling/nulling bd, but this makes no difference. The bitmap is still 'already' recycled as soon it's been re-created (again, intermittently).
Also, when logging like so:
Log.v("NewTag","Backgrounds: "+backgrounds);
I've noticed that when it fails, the reference logged is the same as the previous time. So.....
The Resources
class has caches for resources loaded from your APK. When you recycle the Drawable
and Bitmap
, you ruin the cached objects. There is no way for the Resources
caches to know this, so they happily return you the same object the next time you ask for that resource.
When your app process dies, all memory state is lost, including the resource cache -- so things will work again (once). Note that "exiting" the app or destroying the activity doesn't necessarily mean that your process will die.
Interesting issue. I'm pretty sure, there were some optimization ideas behind it in Android.
If you do need XML's bitmaps:
Resources res = new Resources(getAssets(), new DisplayMetrics(), new Configuration());
bd = (BitmapDrawable) res.getDrawable(R.drawable.bitmap_drawable);
backgrounds = bd.getBitmap();
......
bd.getBitmap().recycle();
bd=null;
backgrounds.recycle();
backgrounds=null;
Optionaly, you can first try to get Bitmap
from standard getResources()
and only then instantiate new resource instance.
If you don't need XML's bitmaps:
Bitmap backgrounds = BitmapFactory.decodeResource(getResources(), R.drawable.test_image);
to get image and
backgrounds.recycle();
backgrounds=null;
to recycle it.
I hope, it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With