How to avoid memory leaks in Android.

July 28, 2018

I have been an android developer for quite some time now. And I realized that most of that time, I tend to spend on adding new features to an app or working on visual enhancements of the app, rather than focusing on the core issues like performance and quality.

So it could cause problems like slowing down device and lag in the device. If an app is heavy it could freeze the device and results in abruptly shut down of the device.

This affects app play store ratings and the number of installs. So I am going to share my experience with Optimization of an android app.

There are a lot of articles on memory leaks and how to fix them, but when I was learning myself, I found that none of them were in one place and it was hard to keep track of it all. So I thought I would collectively post an article on it so that it might help people in the future.

So, let’s begin.

What are Memory Leaks?

A memory leak happens when memory is allocated but never gets freed. Means garbage collector can not take out the trash once we are done with the things. In the app development lifecycle initially, it’s not much problem. But as we go further in development, it gets a bigger problem, Imagine if you don’t take the trash out for 2 weeks! The house starts to smell right?

Similarly, as the user keeps on using our app, the memory also keeps on increasing and if the memory leaks are not plugged, then the unused memory cannot be freed up by the Garbage Collection. So the memory of our app will constantly increase until no more memory can be allocated to our app, leading to OutOfMemoryError which ultimately crashes the app.

How To Check If My App Has Memory Leak?

I am sure everyone on this planet knows how to find memory leaks, but just in case for those who are not aware of it. There is an awesome library called LeakCanary. It is best for finding leaks in the mobile app along with the stack trace.

As I learn from my experience, I have made the checklist of what things should be considered to take care in the context of memory leak.

The checklist:

1. Static activity and view reference:

When we define any static reference to view or any class then it doesn’t get disposed, In short, it doesn’t collect by the garbage collector. Imagine your maid collects trash which only in a trash can, and you throw trash around the house. So your maid doesn’t collect that and it takes space in your house. This same situation happens in a mobile app.

How do we solve this?

Do not use static reference for views and any class. If somehow you need to use static then make it null after it’s work done.

2. AsyncTask Reference:

Consider the following scenario

You are using an asyncTask to get a string value which is used to update the textView in OnPostExecute().

When we create AsynchTask It resides in memory until we don’t make it cancel, even if an activity is destroyed. Since its high priority thread garbage collector can’t take it away.

How Do we solve this?

We should always cancel the asyncTask when activity is destroyed. This is because the asyncTask will still be executing even if the activity is destroyed.

NEVER reference a class inside the activity. If we definitely need to, we should set the class as static as static inner classes don’t hold any implicit reference to its parent activity class.

3. Broadcast receiver:

Consider this scenario – you need to register a local broadcast receiver in your activity. If you don’t unregister the broadcast receiver, then it still holds a reference to the activity, even if you close the activity. Solution to this is quite simple, but you have to remember each time you write Broadcast receiver always call unregisterReceiver in onStop() or onPause().

4. Screen rotation:

When device rotation implies it creates a new activity with requested rotation and discards old activity. So, if any method or reference which refer to the old activity then its become leak, because it can not be freed from memory.

So to prevent this make all reference null so garbage collector can collect it. Sometime it may happen that garbage collector not invoked so we can explicitly call garbage collector.

So Basically we need to consider

Always make sure to unregister broadcast Receivers or timers inside the activity. Cancel any asyncTasks or Threads inside onDestroy().

Always use a weakReference of the activity or view when needed.

Never use static variables to declare views or activity context.

Never reference a class inside the activity. If we need to, we should declare it as static, whether it is a thread or a handler or a timer or an asyncTask.

Use applicationContext() instead of activity context when possible. If you really have to use activity context, then when the activity is destroyed, ensure that the context you passed to the class is set to null.

And That’s It, There are more factors which affects memory usage and memory leaks, I always keep exploring that. I would like to hear more on this, please comment.