5

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,

  • Same bitmap instance, but the problem occurs depending on resizing value.

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

user1746071
  • 51
  • 1
  • 2
  • This question is similar and may have your answer: http://stackoverflow.com/questions/7983321/android-trying-to-use-a-recycled-bitmap-error-with-temporary-bitmaps – XdebugX Dec 06 '12 at 01:19

3 Answers3

6

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.

Edward Falk
  • 9,991
  • 11
  • 77
  • 112
XdebugX
  • 331
  • 3
  • 5
2

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;
}
JRomero
  • 4,878
  • 1
  • 27
  • 49
0

I'd rather suggest to try checking if the bitmap is already recycled before to recycle:

if (!tmp.isRecycled()) tmp.recycle();
USB
  • 53
  • 1
  • 6