Recycle ImageView's Bitmap

37,667

Solution 1

In your onDestroy method you could try something like this:

ImageView imageView = (ImageView)findViewById(R.id.my_image);
Drawable drawable = imageView.getDrawable();
if (drawable instanceof BitmapDrawable) {
    BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
    Bitmap bitmap = bitmapDrawable.getBitmap();
    bitmap.recycle();
}

The cast should work since setImageBitmap is implemented as

public void setImageBitmap(Bitmap bm) {
    setImageDrawable(new BitmapDrawable(mContext.getResources(), bm));
}

Solution 2

If you set the same bitmap object on all your ImageViews, it shouldn't throw an OutOfMemoryError. Basically, this should work:

WeakReference<Bitmap> bm = new WeakReference<Bitmap>(Bitmap.createBitmap(3000 + 3000, 2000, Bitmap.Config.ARGB_8888));

Canvas canvas = new Canvas(bm.get());
canvas.drawBitmap(firstBitmap, 0, 0, null);
canvas.drawBitmap(bm, firstBitmap.getWidth(), 0, null);

imageView1.setImageBitmap(bm.get());
imageView2.setImageBitmap(bm.get());
imageView3.setImageBitmap(bm.get());
imageView4.setImageBitmap(bm.get());
imageView5.setImageBitmap(bm.get());
// ...

If this doesn't work, it simply means your bitmap is too large (6000x2000 pixels is about 12 megabytes, if I calculated right). You can either:

  • make your bitmap smaller
  • cut down on other stuff that use a lot of memory

Solution 3

Devconsole's answer is great, but you can also store all bitmap objects in list like member of your class, and then recycle them in cycle when the onDestroy() method of activity (or some other release lifecycle method of component where you use bitmap) will be called.

Share:
37,667
Peter Olsbourg
Author by

Peter Olsbourg

Updated on February 17, 2020

Comments

  • Peter Olsbourg
    Peter Olsbourg about 4 years

    I have something like this:

    Bitmap.Config conf = Bitmap.Config.ARGB_8888;
    WeakReference<Bitmap> bm = new WeakReference<Bitmap>(Bitmap.createBitmap(3000 + 3000, 2000, conf));
    
    Canvas canvas = new Canvas(bm.get());
    canvas.drawBitmap(firstBitmap, 0, 0, null);
    canvas.drawBitmap(bm, firstBitmap.getWidth(), 0, null);
    
    imageView.setImageBitmap(bm);
    

    And I apply this on more than 10 imageView's which are created one by one. Whenever I create new ImageView, I want to recycle the 'bm' object from the first one, cause this code up there, causes my heap to grow more and more and then throw OutOfMemoryError, so I do:

    bm.recycle()
    

    right after I set the Bitmap (bm) to the imageView object. This causes exception that the ImageView's canvas wants to draw recycled Bitmap.

    What is the way to recycle a Bitmap that has already been put as image on ImageView?

    Thanksb

  • user802421
    user802421 over 12 years
    In his case, maybe it should be done right before he call setImageBitmap() again.
  • Peter Olsbourg
    Peter Olsbourg over 12 years
    I don't have access to the Activity where the ImageView is used, I just implement custom ImageView, so I thought the ImageView class itself has some mechanism as destructor in C++ or any signal to know that the very instance of that ImageView is not used anymore..
  • Peter Olsbourg
    Peter Olsbourg over 12 years
    The thing is that even though I recycle the Bitmap created with .createBitmap, the heap grows everytime this methods ends. I recycle it right after to check if it's ok - nope, the heap grows. So I suppose this is the leak..
  • hasan
    hasan over 10 years
    Do I have to do this for all images or just for large ones. can't I just assign another image to the image view?
  • diego nunes
    diego nunes almost 9 years
    12Mpx != 12MB. It is probably taking a lot more memory than just 12MB. A 12Mpx Bitmap can take more than 35MB.