Bitmap Pool in Android

Authors
  • Amit Shekhar
    Name
    Amit Shekhar
    Published on
Bitmap Pool in Android

I am Amit Shekhar, a mentor helping developers in getting high-paying tech jobs.

In this blog, we will learn about the bitmap pool in Android.

Image heavy applications have to decode many images, so there will be continuous allocation and deallocation of memory in application. This results in frequent calling of the Garbage Collector (GC). And if you call the GC too many times, your application UI freezes.

If you want to read more about the mechanics of UI freezes and how to avoid them, here’s a good primer.

Glide and Fresco use the Bitmap Pool Concept to reduce GC calls as much as possible and make the UI responsive.

By using the Bitmap pool, they avoid continuous allocation and deallocation of memory in our application and reduce GC overhead.

Let's understand what is bitmap pooling.

What is bitmap pooling?

Bitmap pooling is an implementation that tries to reuse the memory of the bitmaps already available instead of allocating new memory every time. Suppose we need to load a bitmap, we first check our pool to see if there is any bitmap available. If it is available, we take a bitmap from the pool and reuse its memory to load our new bitmap otherwise we create a new bitmap. In case, if we do not need any bitmap, we put that bitmap into that pool instead of recycling it so that we can reuse the memory of that bitmap when needed for a new bitmap.

We put constraints on the memory size of the pool as we put constraints on the memory size of a cache.

This is possible by using the inBitmap property of the Bitmap. (which reuses bitmap memory).

Let's say we have to load two bitmaps (bitmapOne, bitmapTwo) one by one. When we load bitmapOne, it will allocate the memory for bitmapOne. Then if when we no longer need bitmapOne, we do not recycle the bitmap (as recycling involves calling GC). Instead, we use this bitmapOne as an inBitmap for bitmapTwo. This way, the same memory can be reused for bitmapTwo.

Let's say, we are showing a bitmapOne into the imageView.

Bitmap bitmapOne = BitmapFactory.decodeFile(filePathOne);
imageView.setImageBitmap(bitmapOne);

Now, let's say, we do not need image bitmapOne and we have to set another bitmap in imageView.

final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePathTwo, options);
options.inMutable = true;
options.inBitmap = bitmapOne;
options.inJustDecodeBounds = false;
Bitmap bitmapTwo = BitmapFactory.decodeFile(filePathTwo, options);
imageView.setImageBitmap(bitmapTwo);

Note:

  • On API Level 19+, the Bitmap needs to be the same size or larger than the Bitmap that we are trying to decode. Otherwise, the Bitmap will be ignored and we will get a new Bitmap.
  • On older devices, the Bitmap needs to be the same size (resolution) as the Bitmap that we are trying to decode. Otherwise, the Bitmap will be ignored and we will get a new Bitmap.

This way we are not allowing the GC to be called again and again as we are not leaving off the reference of the bitmapOne, instead we are loading the bitmapTwo in the memory of bitmapOne.

These libraries create a bitmap pool of bitmaps.

We can say that the bitmap pool is a list of bitmaps that are no longer needed but are available for reuse to load the new bitmap into the same memory.

When any bitmap is available for recycling, these libraries just push the bitmap into that bitmap pool.

When these libraries have to load the new bitmap, they just get a bitmap that can be reused to load the new one to reuse the same memory from that bitmap pool. Hence no recycling, and no GC calls.

And we have responsive UI.

This is how Bitmap pooling helps us. I hope you must have understood the bitmap pool in Android.

Master Kotlin Coroutines from here: Mastering Kotlin Coroutines

That's it for now.

Thanks

Amit Shekhar

You can connect with me on:

Read all of my high-quality blogs here.