One of the most common causes of fragmentation is limited hardware specs, whether it’s small RAM, slow processor or low resolution screen, they all create a challenging environment for Android application developers aiming for ultimate device compatibility. A lot of Android developers face memory issues on low costs devices and this is how it usually goes: You created a bitmap and your application throws an OutOfMemory exception but there is still a lot of free memory and you are left wondering: What is the source of problem? How to limit this? Let me explain.
Android has two kinds of stacks – one for application and one for graphics. In an activity method setContentView(int i) Android inflates XML layout and initializes all objects. In this part of code every graphics object is located in a memory. This same situation happens when your application creates a Bitmap object. Android creates object in the graphics stack and sends reference to it and sometimes, for one reason or another, you will receive an OutOfMemory exception.
I discovered this problem when I was testing my application with our product – Testroid Cloud ( Online cloud of real Android devices for running automated tests for Android applications).
When I was running my automated tests on all Android devices, I was constantly getting OOM exceptions on same devices – mostly on low spec ones. It was very strange because when I started debugging, I found out that there was still free memory left but my application just could not access it. I tried to search for a solution but all tracks pointed to a comment from a Google staff: “Your application uses too much graphics and you don’t manage your memory”. It was a strange answer because Java has garbage collector and, because of that, I thought I don’t have to delete objects manually.
Luckily my friend sent me a good article about strong and weak references (http://weblogs.java.net/blog/2006/05/04/understanding-weak-references). After reading this I understood what I was doing wrong. Loading every bitmap in application to a HashMap at the startup was a very bad idea! Every time in onStart() method I created a new HashMap object with reference to a new bitmap object. All old bitmaps were always still in memory. They had a strong reference so garbage collector removed HashMap object but not every bitmap from graphics stack.
To fix this I created a new class to manage bitmaps. This class recycles them manually when they were removed or updated. I call it “BitmapManager”. In my opinion this is the best solution to solve my OOM problem.
How to create your own version:
Create an object to organize bitmaps (in my project I used HashMap<String,Bitmap>)
Create your own method to create, update and remove bitmaps. You should run method recycle() on old bitmaps.
If you have to download an image from web you should run all download threads from BitmapManager. This way you won’t have any problems with lost threads.
Clear and recycle bitmaps in onStop() method and reload them in onStart() method
Never send a bitmap in Message via Android Handler. It will create clone object, so you will lose original reference.
With this solution you can resolve almost all problems with bitmaps and out of memory exceptions. Finally one more word of caution: You should watch out on open recycled bitmaps. You will receive an exception from ImageView.