I've got very critical problem. Only Android 4.1, Bitmap is recycled automatically! I didn't call recycle() in my code! My project works fine in other OS versions( ~ 4.0.3) with any resolutions. Other projects have same problem, too.
All image files are in drawable-nodpi folder. I resized them to fit for resolution of any devices, always.
public Bitmap GetBitmap(int resource){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDither = true;
options.inPurgeable = true;
Bitmap tmp = null;
try{
tmp = BitmapFactory.decodeResource(mResources, resource, options);
}catch(OutOfMemoryError e){
options.inSampleSize = 2;
tmp = BitmapFactory.decodeResource(mResources, resource, options);
}
return tmp;
}
public Bitmap GetScaledBitmap(int resource, int width, int height, boolean filter){
Bitmap tmp = GetBitmap(resource);
Bitmap img = Bitmap.createScaledBitmap(tmp, width, height, filter);
tmp.recycle();
tmp = null;
return img;
}
In my testing,
ex) int width = 100;
Bitmap imgStar = MyResourceManager.getInstance().GetScaledBitmap(R.drawable.star, width, width , true); -> returns recycled instance.
width = 200;
imgStar = MyResourceManager.getInstance().GetScaledBitmap(R.drawable.star, width, width, true); -> returns normal instance.
In different resolutions, imgStar works fine, but the problem occurs in other bitmap instance. Similarly, When I change resizing value, it works fine.
In same resolution, the problem occurs in other bitmap instance, if I change the name of image files folder. drawable-nodpi -> drawable -> drawable-ldpi, ..., drawable-xdpi.
Same resizing value, it works fine if I put other resource id. ex)
int width = 100;
Bitmap imgStar = MyResourceManager.getInstance().GetScaledBitmap(R.drawable.star, width, width , true); -> returns recycled instance.
imgStar = MyResourceManager.getInstance().GetScaledBitmap(R.drawable.diamond, width, width, true); -> returns normal instance.
Please... what can I do?! T ^ T
The reason you're getting different results from different sizes may be because createScaledBitmap will return the original object if it is the same size you are scaling to.
I had the same problem, doing the same thing you are. I was able to fix it this way:
public Bitmap GetScaledBitmap(int resource, int width, int height, boolean filter) {
Bitmap tmp = GetBitmap(resource);
Bitmap img = Bitmap.createScaledBitmap(tmp, width, height, filter);
//copy the image to be sure you are not using the same object as the tmp bitmap
img=img.copy (Bitmap.Config.RGB_565,false);
tmp.recycle();
tmp = null;
return img;
}
Here I copied the bitmap to make sure it wasn't just a refernce to the tmp bitmap object before I recycled the tmp bitmap. Of course you can use any bitmap config you need.
I believe XdebugX was correct in his finding although you don't need to create a copy. Simply check if the memory locations are the same between your resized and original bitmaps.
public Bitmap GetScaledBitmap(int resource, int width, int height, boolean filter){
Bitmap tmp = GetBitmap(resource);
if (tmp == null) {
return null;
}
Bitmap img = Bitmap.createScaledBitmap(tmp, width, height, filter);
/***
* Bitmap#createScaledBitmap will return the original object
* if it is the same size you are scaling to.
*/
if (tmp != img) {
Log.d(TAG, "Full size image recycled");
tmp.recycle();
} else {
Log.w(TAG, "Resized bitmap was the same as the fullsize bitmap");
}
return img;
}
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