1

I have created Bitmap like below,

// create bitmap in the below line Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.googlelogo320x480); And I have set it to an ImageView.

my questions are: 1> Do I need to explicitly call Bitmap.recycle() on the above Bitmap? 2> If yes then when should I call it? I have tried calling it immediately after the 3rd line i.e, after setting the bitmap to an ImageView, however I get an exception that Canvas trying to draw a recycled Object. 3> Is it going to be a memory leak if recycle() is never called on the Bitmap in my code? P.S: I am working on ICS or above.

Guna
  • 338
  • 6
  • 17
  • use `BitmapOptions` - `inSampleSize`(?) to reduce the size you load to memory. This will avoid OOM until it is released by the OS. – IAmGroot Oct 27 '12 at 14:44

3 Answers3

4

In this particular case, no, you shouldn't call recycle(); the ImageView will call recycle() when it is done with it. This has been true for a while, ICS did nothing to change this fact.

You need to call recycle() when your code is done with the image. For example if you were applying 10 filters to one image and generating a new Bitmap on each step, you SHOULD call recycle() on the old Bitmap after each step.

That said, you can't have an unlimited number of Bitmaps at the same time, especially large ones. That's when you need to be clever and load/unload dynamically.

dmon
  • 30,048
  • 8
  • 87
  • 96
  • Thanks for the answer, So I assume the Bitmaps I am creating and adding to ImageView need not be recycled by myself, as long I am not changing the ImageView to a different Bitmap. Once the View is gone or during Orientation changes, then the ImageView by itself will call the recycle on my Bitmap. Is my understanding correct? Also is there any tool/way to find Bitmap Memory leaks? – Guna Oct 27 '12 at 15:01
  • One more quick question, what is the difference between bmp = null & bmp.recycle()? I have used bmp = null; immediately after the bitmap is set to ImageView, with this change no crash was seen. However when i call a bmp.recycle() after setting to ImageView it crashes saying canvas trying to draw recycled bitmap. Is bmp= null, setting really required?? – Guna Oct 27 '12 at 15:05
  • `bmp = null` just tells the system that you no longer need the Bitmap. The memory will be freed whenever the GC kicks in. If you call `recycle()` that frees up the memory immediately. – dmon Oct 27 '12 at 18:48
  • For orientation changes, the ImageView will release the bitmap and eventually the GC will take care of it. The Memory shouldn't leak. – dmon Oct 27 '12 at 18:49
2

Not calling recycle() will not cause memory leak, but it may cause your app to go over the memory limit and explode, see below to see whether your app qualify:

  1. If you are only interested in ICS and above, you shouldn't need to worry about calling recycle(), as a Bitmap's actual backing data is stored in Dalvik controlled memory. Therefore as long as you don't keep a reference to a Bitmap around, Dalvk should be able to GC it with no problem.
  2. Even if you wish to support Android 2.3 or prior, Bitmaps will eventually be released, so if your app is not Bitmap intensive, you shouldn't need to worry about it either.
  3. BUT, if you are supporting Android 2.3 or prior, and use lots of Bitmaps, then you should recycle a Bitmap as soon as it is done.
Kai
  • 15,284
  • 6
  • 51
  • 82
  • Yes I am using lots of bitmaps in my app, so even with ICS or above I might sill need to call recycle? Also in your first point "Therefore as long as you don't keep a reference to a Bitmap around, Dalvk should be able to GC it with no problem." not keep a reference around means? I am setting each bitmap to a Imageview, based on orientation changes or whenever images needs to be updated I am creating new Imageview & new bitmap instances again in a for loop. – Guna Oct 27 '12 at 14:26
  • If there's nowhere in your code that refers to a ImageView, then it will be release by Android at an indeterminate time. If you are allocating lots of Bitmaps in a for loop, then you can try put _System.gc()_ before the for loop, and test on actual devices to see if you actually encounter OoM. – Kai Oct 27 '12 at 14:42
  • I have already encountered an OOM not in this activity some other file which will be triggered by the call from my activity. In that file they are trying a creating anew Bitmap, thats where it is throwing OOM. – Guna Oct 27 '12 at 14:49
  • Also one more OOM in my own code is, before the for loop which creates many bitmaps, I am actually trying to add decode 2 Bitmaps, which are around 9KB, as below code, Bitmap bmp = BitmapFactory.DecodeResource(resources, R.drawable.myImage); Here also it is crashing as OOM, I have fixed this to some extent by using sampling rate. However was just wondering why the OOM happend in the first. Also this sampling fix will reduce the probability, how ever it wont guarantee to eliminate the OOM issue while decoding the Bitmap resource – Guna Oct 27 '12 at 14:53
  • One possible reason is that you simply are creating too many Bitmaps or their size too large. Another reason may be the way you are creating them: through a for loop. Doing so may not give Android enough time to GC. You can eliminate this possibility by calling Thread.yield(); or Thread.sleep(50); after each Bitmap creation in the for loop. If you still get OoM, then it's probably because reason #1. – Kai Oct 27 '12 at 15:58
0

try this

if (myBitmap != null) {
    myBitmap.recycle();
    myBitmap = null;
}
Bitmap original = BitmapFactory.decodeFile(myFile);
myBitmap = Bitmap.createScaledBitmap(original, displayWidth, displayHeight, true);
original.recycle();
original = null;
Devangi Desai
  • 1,355
  • 12
  • 17
  • My question was is it really required on ICS or later versions of Android. Also if required then when should this be called? onDestroy() of an activity will be too late, since by then I will be run OOM exception – Guna Oct 27 '12 at 14:11