Table of Contents

Memory leaks in Android — identify, treat and avoid

by Johan Olsson

Original: https://medium.com/freenet-engineering/memory-leaks-in-android-identify-treat-and-avoid-d0b1233acc8

Registering listeners

Don't forget to unregister

To find a leak use “Android Monitor” in Android Studio. Make dump and then in “Analyzer Tasks” check “Detect Leaked Activities”.

Inner classes

Inner classes creates implicit reference to the enclosing class. Especially inner classes implementing AsyncTask can have this problem, because Activity have different life cycle as inner class. Activity can be destroyed, but the reference to it will be hold, because of inner AsyncTask class. Possible solution: The inner class should be made static.

If the inner class needs some data from enclosing task, it should be delivered to it through constructor. If this data contains Context (if we for example need a textView from an activity, this textview will contain Context), then we can use WeakReference for it. Example:

private static class BackgroundTask extends AsyncTask<Void, Void, String> {

  private final WeakReference<TextView> textViewReference;

  public BackgroundTask(TextView resultTextView) {
        
    this.textViewReference = new WeakReference<>(resultTextView);
       
  }
        ...

Anonymous classes

Anonymous classes have the same problem as inner classes: they hold instance to the enclosing class. We can use here the same solution.

Conclusion

Each non-static inner class will have an implicit reference to its outer class instance which may result in unwanted behaviors. Instead define these classes as static and store life cycle references needed as WeakReferences.

Android offers a wide variety of ways to get work off the main thread such as HandlerThread, IntentService and AsyncTask, each with their own strengths and weaknesses. In conjunction, Android offers several mechanisms to propagate information back to the main thread in order to update the UI. The BroadcastReceiver is one very capable tool to achieve this.

When coding in a garbage collected language it’s easy to make the assumption, that memory management does not have to be taken into consideration. Our examples clearly show that this is not the case. Therefore, make sure that your allocated resources are all collected as expected.