Android: How does Bitmap recycle() work?

AndroidBitmap

Android Problem Overview


Let's say I have loaded an image in a bitmap object like

Bitmap myBitmap = BitmapFactory.decodeFile(myFile);

Now, what will happen if I load another bitmap like

myBitmap = BitmapFactory.decodeFile(myFile2);

What happens to the first myBitmap? Does it get Garbage Collected or do I have to manually garbage collect it before loading another bitmap, eg. myBitmap.recycle()?

Also, is there a better way to load large images and display them one after another while recycling on the way?

Android Solutions


Solution 1 - Android

The first bitmap is not garbage collected when you decode the second one. Garbage Collector will do it later whenever it decides. If you want to free memory ASAP you should call recycle() just before decoding the second bitmap.

If you want to load really big image you should resample it. Here's an example: https://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue/823966#823966.

Solution 2 - Android

I think the problem is this: On pre-Honeycomb versions of Android, the actual raw bitmap data is not stored in VM memory but in native memory instead. This native memory is freed when the corresponding java Bitmap object is GC'd.

However, when you run out of native memory, the dalvik GC isn't triggered, so it is possible that your app uses very little of the java memory, so the dalvik GC is never invoked, yet it uses tons of native memory for bitmaps which eventually causes an OOM error.

At least that's my guess. Thankfully in Honeycomb and later, all bitmap data is stored in the VM so you shouldn't have to use recycle() at all. But for the millions of 2.3 users (fragmentation shakes fist), you should use recycle() wherever possible (a massive hassle). Or alternatively you may be able to invoke the GC instead.

Solution 3 - Android

You will need to call myBitmap.recycle() before loading the next image.

Depending on the source of your myFile (E.g. if it is something you have no control over the original size), when loading an image instead of just simply resampling some arbitrary number, you should scale the image to the display size.

if (myBitmap != null) {
    myBitmap.recycle();
    myBitmap = null;
}
Bitmap original = BitmapFactory.decodeFile(myFile);
myBitmap = Bitmap.createScaledBitmap(original, displayWidth, displayHeight, true);
if (original != myBitmap)
    original.recycle();
original = null;

I cache the displayWidth & displayHeight in a static that I initialized at the start of my Activity.

Display display = getWindowManager().getDefaultDisplay();
displayWidth = display.getWidth();
displayHeight = display.getHeight();

Solution 4 - Android

Once bitmap had been loaded in memory , in fact it was made by two part data. First part include some information about bitmap , another part include information about pixels of bitmap( it is maked up by byte array). First part exisits in Java used memory, second part exisits in C++ used memory. It can use each other's memory directly. Bitmap.recycle() is used to free the memory of C++. If you only do that,the GC will collection the part of java and the memory of C is always used.

Solution 5 - Android

Timmmm was right.

according to : http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

In addition, prior to Android 3.0 (API Level 11), the backing data of a bitmap was stored in native memory which is not released in a predictable manner, potentially causing an application to briefly exceed its memory limits and crash.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAnuj TenaniView Question on Stackoverflow
Solution 1 - AndroidFedorView Answer on Stackoverflow
Solution 2 - AndroidTimmmmView Answer on Stackoverflow
Solution 3 - AndroiddjunodView Answer on Stackoverflow
Solution 4 - AndroidAllenView Answer on Stackoverflow
Solution 5 - AndroidJianView Answer on Stackoverflow