Detect and Fix Memory Leaks in Android

In this post, we will see the ways of detecting memory leaks in Android and review how the same can be applied to solve the issue.

Usually, an Android application can have two kinds of lags, One is ANR (Application Not Responding) and the other is a Crash.

ANR happens when the process that is running on the UI thread consumes a lot of time (probably 5 seconds) than normal. When such issue happens in an Application, the GUI (Graphical User Interface) as a mechanism will lock up the processes and try prioritizing the UI. This is when you will not be able to touch any views on the application such as a button. After the 5 second wait time, if still, the GUI couldn’t recover the thread, it will display an ANR dialogue box with options for the user to either wait or to force kill the app.

A Crash happens when there is an exception encountered within the application and thrown by the system, but not handled properly by the app. That is why it is always good to use try catch finally block where ever needed. Some of the examples of crash are such as Nullpoint, classNotfound, typecast Exception, etc,. The user will never understand why the app responded in such manner nor cannot see what caused the crash, All they will see is a dialog box with a message telling that the app has force closed unexpectedly.

So What does a memory leak clearly mean?

A memory leak is the state of a class where few objects of the class are not utilized by the app at some point, and the Garbage Collector still thinks that they are a part of the app. It’s because you still hold a reference to the context that prevents the Garbage Collector from understanding it. OutOfMemoryError is an example of memory leak error. ANR also happens because of such memory leak issues.

Keeping the garbage within the class is not a good practice. We should use this piece of Java Virtual Machine called Garbage Collector to clean out the stuff.
You need to free the references to the objects once their usage is complete. This is an easy way to follow a memory leak free programming. If the objects are kept referenced for the end of the lifecycle, it always leads to memory leaks.

Since Android devices are designed with less memory, it is usual that Memory leaks can happen so easily. Also, they are the biggest issue any Android device can have. Why allow memory leaks when it is easy to keep track of them while building the application itself.

1. Having background references of UI specific objects

Don’t hold background references of UI specific objects, as it always leads to memory leaks.

Another issue is when we use views as a collection. Avoid this practice since they may have views using an unclear memory pattern. Also, WeakHashMap store views as hard-coded values, and it is better to avoid it.

2. Using static views and Context

While it is good to assign values to variables to static in some cases, it is not always a good idea to do it to Views as well. If views are declared static then they will be available until the end of the application cycle.

Similarly, avoid making the context static.

 

Context are not the same. They are of three types such as Context, Application Context, and Activity Context.

1. Application Context

Application context should be used whenever it can be used and Activity context must be used only when it is required.

Application Context will stay the same throughout life of the application. The base class of Application Context is Activity.

Activity.getApplicationContext();

getApplicationContext() usages:

To create new adapters, listeners, etc,.

ListAdapter adapter = new SimpleCursorAdapter(getApplicationContext(), ... );

To access SharedPrefs

getApplicationContext().getSharedPreferences("name","mode");

To access components implicitly such as Content Provider, Broadcast Receiver, Intents, etc,.

getApplicationContext().getContentResolver().query(uri, ...);

 

2. Activity Context

Activity Context is life cycle based. It gets destroyed on call of onDestroy() method in the activity. ContextWrapper is the base class of an Activity context.

ContextWrapper.getBaseContext();

When we need to call a new activity in connection with the present activity, we will simply use Activity Context in the Intent (since ContextWrapper allows to access a context from within another context). If Application Context is used instead of Activity Context, then we will need to set the flag Intent.FLAG_ACTIVITY_NEW_TASK  to treat it as a new task.
The Context returns the context of the currently active activity. The base class of Context is View.

View.getContext()

getContext() usages:

To create new Views.

EditText et = new EditText (getContext());

// This creates a new EditText view keeping the current active activity as reference.

 

3. Unregister the listeners after its use

If you do not unregister your listeners, it will keep the activity alive and will wait for the listener till the finish. Timely unregister them from within onPause(), onStop(), or onDestroy() methods.

 

4. Non Static Inner Classes

If you are using inner classes, be sure you make them static.

 

5. Using anonymous class

They are similar to non-static inner classes. Avoid using anonymous classes.

 

How easy is it to detect memory leaks?

When scanning and detecting the memory leaks are tester things, there comes the lifesaver ‘LeakCanary ‘. LeakCanary runs along with the application and helps detect the leaks easily, and also notify us about the leaks.

Leave a Reply

Your email address will not be published. Required fields are marked *