Avoid Out-Of-Memory Problems in Android

It’s Java so you don’t need to worry  – the garbage collector ‘just does it’, right?

NOT!

java.lang.OutOfMemoryError: Bitmap Size Exceeds VM Budget is a common error and don’t we know it!  The garbage collector isn’t totally magic and no guarantee that your app cannot / will not leak memory.  There are various deliberate approaches / considerations that should be taken to avoid memory problems:

  1. Frequently, when changing orientation in an app that uses lots of bitmaps, you get the bitmap memory message – we’ve for sure seen this in alpha versions of our app.  Android destroys your Activity when changing orientations, but often leaves dangling references from the previous instance.  So it pays to trap onDestroy() and deliberately zap all resources.  Here is a way to do it. It’s probably a good idea to put this into every single one of your Activity classes.
  2. It’s a good idea to run the Monkey as part of your test program:

    adb shell monkey -p your.package.name -v 500

    The Monkey can also be invoked directly from Eclipse.

  3. Carefully manage references to Context.

    For example, you might think it’s a Good Idea to have a static variable for a resource like a Drawable which could enable to to reload an Activity faster and minimise garbage collection cycles which can momentarily freeze your handset. But static references to resources are also a great way to leak memory.  If  you really want to speed re-loading of an Activity, consider using the ApplicationContext singleton available from Context.getApplicationContext() or Activity.getApplication().

    The article here has more detail about this – and also comments about care you need to take when using inner classes.

  4. Use the allocation tracker (part of the Android SDK) to work out where your memory is going.  You could combine this with testing with the Monkey.
  5. Watch out for threads that allocate resources, e.g. in a map viewer that could be loading tiles in the background. You need to make sure that the threads are properly terminated when the Activity is destroyed.