Everything You Need To Know About Context-Related Memory Leaks In Android

This article explains context-related memory issues in Android in an easier way. Context-related memory leaks happen in Android if you are holding on to an object for a longer time.

Let’s admit it! Almost all developers, at some point in our lives, have faced this so-called “context-based” memory leak issue while writing Android apps.

We all as Android programmers, at some point in our lives, have faced this “so-called” context-based memory leak issue in Android.

Developers that have significant experience in building Android apps would better be able to handle context related issues better, but it is a nightmare for junior developers for sure! I have been down that path and had my fair share with context-related issues.

I am glad that I was quickly able to figure out most of the context related challenges. If you are a junior to mid-level dev fighting to work through context, this article is for you. I will try to boil down my thoughts on how to effectively understand and sort out context-related memory issues in your Android apps.

What exactly is a memory leak in Android?

 
An Android app needs memory to run effectively in a device. After the app completes a function it carries out the memory locked for such operations has to be freed again. To do this, Android has something called Garbage collection (or GC). A memory leak usually happens when this Garbage collector is unable to clean some “garbage-data” in the memory.

The “garbage-data” that I am referring above are usually some objects (created when the app is carrying out a process) that are no longer useful for the app.

Garbage Collector in Android usually works like this,

  • Step #1
    It traverses all the objects from GC roots and marks objects that have a reference from the GC roots as active objects

  • Step #2
    Those objects that no longer have a reference from the GC roots are cleaned up or removed from the memory

  • Step #3
    All the active objects are then rearranged in the memory

Poor programming practices usually induce memory leaks by preventing Garbage Collector from cleaning them. Below image shows a visual representation of how poor programming practices hamper garbage collector's performance.

What are Context-related Memory leaks in Android?

Now that you understand what memory leaks are, let’s dive into the most commonly faced memory leak issue known as “Context-based” memory leak.

What is Context in Android?

A “Context” in Android is declared as an abstract class, whose implementation is provided by the Android OS. This class furtherly allows access to the other important application-specific resources such as launching activities, loading common resources, displaying toast messages, broadcasting and receiving intents, etc.

Let’s understand Context by relating it to a real-life analogy.

A boss has an assistant to help him reduce his focus on the less-important things, like getting coffee at work, documentation with the sourcing department, managing files, to name a few. His assistant is amazing and does everything he needs. For most of the time, the boss doesn’t even know what software his assistant uses to manage his files.

So, how does that correlate with our Android app? Well,

  • Boss is your app’s UI that has no idea of what’s happening in the other layers
  • Assistant is Context that helps the Boss in understanding what’s happening
  • Assistant (Context) is the only person who’s aware of what file is where.

In short, Assistant is the access point for the Boss to access and consume resources, and help with even learning the most basic things that happen around the office. Let’s now merge it completely with Android apps and say that “Your app’s UI needs context to access and learn about resources. On its own, it knows nothing”.

Context class is often called whenever there’s any need to fetch information about the activities or locate/consume different resources within an Android app.

There are many types of Context subclasses such as Activity context, Application context, Service context, etc that extends Context and helps them provide their own functionalities. If you look closely at the Android documentation, the hierarchy of these classes looks something like this:

Context

  • ContextWrapper
  • Application
  • ContextThemeWrapper
  • Activity
  • Service
  • IntentService
Different Methods to define Context in Android

There are several methods by which you can invoke a context in Android such as:

  • this / getActivity() - this is just a current activity we are in
  • getContext() - getContext is related with View or it’s the View’s current context
  • getBaseContext() - It is used when you want to override a context with the older one
  • getApplicationContext() - It gives you the access to applications context

Context-related memory leaks in Android

These Contexts are often primary suspects of Android memory leaks when developers use them without paying close attention.

As already mentioned above, you will need to define a Context to access the app’s resources and environment data. Hence, all widgets in an Android app receive Context as a parameter in the constructor, holding a reference to the entire activity of the application. This also includes its View hierarchy and all other resources. Hence, if you leak the context then you will leak memory.

I spoke about Context-related memory leaks, with them I meant that there will be a reference to that Context that lives long in the memory, preventing the Garbage collector from removing it.

Hence, I would suggest you do not hold Context longer than it is required. Else it would trigger memory leaks.

How to avoid Context-related Memory leaks in Android?

Following are some ways by which you can avoid Context-related memory leaks in Android,

#1 Refrain from passing Context objects further that your Activities and Fragments

Don’t pass Context objects unless you actually need to pass them. I see that a lot of developers pass Context related objects in their apps. You should be more careful with them.

#2 Always use Application Context when you need to create a singleton object for your application

An application Context should be used only if you need to create a singleton object.

For instance, if you need to create a singleton object for your application that requires the Context to load resources, then you should pass the Context as an Application Context. Consider the following code as a reference:

  1. public class CustomManager {  
  2.     private static CustomManager singleInstance;  
  3.     public static CustomManager getInstance(Context context) {  
  4.         if (singleInstance == null) {  
  5.             //Always pass in the Application Context  
  6.             singleInstance = new CustomManager(context.getApplicationContext());  
  7.         }  
  8.         return singleInstance;  
  9.     }  
  10.     private Context mContext;  
  11.     private CustomManager(Context context) {  
  12.         mContext = context;  
  13.     }  

 

In the above code sample, we have passed Application Context by calling context.getApplicationContext( ). This Context will live as long as your application is alive. Hence, it makes sense to use Application Context in this case.

You can’t pass Activity Context in such cases, as doing so will lead to memory leaks. If you pass Activity Context in such cases, it will keep a reference to the activity which can’t be removed by Garbage collector

Avoid keeping a long-lived reference to the Activity’s context

An Activity Context should have the same lifecycle as an activity and it should be destroyed once the activity is destroyed probably due to screen orientation changes. In case the reference to Activity's Context lives longer, it will induce a memory leak.

The Rule of Thumb

As a general rule of thumb, you should use the context for the component you are working in. So, for instance - if you are working in an activity then use Activity context. As long as the activity is needed, you can safely hold the reference to that context

Always use the application context if you are saving the reference to a context from an object that lives beyond the scope of your Activity or service.                                    

Conclusion

These are some observations on my part of handing Context while developing Android apps. I feel that these are some easy to follow principles on handling context-related memory leaks and no matter your experience, it is extremely easy to adhere to these rules to avoid them.