Memory Leaks On Android

4 Min. Read
Sep 29, 2019

What is a memory leak in android?

Many a time we see ANR(Application Not Responding) dialog while using android apps, lags in our apps, we also see OutOfMemoryError in Android Studio while building apps. All these kinds of stuff happen due to memory leaks. Some objects are not even recognized by garbage collector as garbage. In these situation you can not do anything.

Holding reference of objects that are not required anymore is a bad practice, freeing objects reference after being served is helpful for the garbage collector to kill that object, that eventually helps yourself in memory leaks issues. If you keep objects reference unnecessarily, it only leads to memory leaks. Memory leaks can happen easily on an android device if not taken care of while building apps, as android devices are provided with very less memory.

Memory leaks are the biggest issue for any android app, in spite of being the biggest issue, it is not much difficult to avoid it, if we give importance while building the app. We need to keep few things in mind while building memory leaks free apps. Memory leaks can be caused by various ways in android as it is the easiest thing to do.

Why Memory Leaks Happen in Android.

The Following are the reasons that causes a memory leaks in android:

1. Using inner class

If you are using an inner class, use this as static because static class does not need the outer class implicit reference. Using inner class as non static makes the outer class alive so it is better to avoid. And if you are using views in static class, pass it in the constructor and use it as a weak reference.

Use something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class MainActivity extends AppCompatActivity {

    TextView textView;
    AsyncTask asyncTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textView);

        asyncTask = new MyBackgroundTask(textView).execute();
    }

    @Override
    protected void onDestroy() {
        asyncTask.cancel(true);
        super.onDestroy();
    }

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

        private final WeakReference<TextView> textViewReference;

        public MyBackgroundTask(TextView textView) {
            this.textViewReference = new WeakReference<>(textView);
        }

        @Override
        protected void onCancelled() {
        }

        @Override
        protected String doInBackground(Void... params) {
            return "some text";
        }

        @Override
        protected void onPostExecute(String result) {
            TextView textView = textViewReference.get();
            if (textView != null) {
                textView.setText(result);
            }
        }
    }
}

2. Using anonymous class

This is very similar to non static inner classes as it is very helpful but still avoid using an anonymous class.

3. Using views in collection

Avoid putting views in collections that do not have clear memory pattern. WeakHashMap store views as values. Since WeakHashMap store views as a hard reference it is better to avoid using it.

4. Using Context

Be careful while using context, deciding which context is suitable at places is most important. Use application context if possible and use activity context only if required

For more information please refer

5. Using static views

Do not use static views as it is always available, static views never get killed.

5. Using static context

Never use context as static.

1
2
3
4
5
6
public class MainActivity extends AppCompatActivity {

  private static Button button; //NEVER USE LIKE THIS
  private static Context context; //NEVER USE LIKE THIS TOO

}

How to Avoid Memory Leaks

Use memory carefully with above tips can bring benefit for your application incrementally, and make your application stay longer in system. But all benefit will lost if memory leakage happens. Here are some familiar potential leakage that developer needs to keep in mind.

  1. Remember to close the cursor after querying the database. If you want to keep the cursor open long-term, you must use it carefully and close it as soon as the database task finished.

  2. Remember to call unregisterReceiver() after calling registerReceiver().

  3. Avoid Context leakage. If you declare a static member variable “Drawable” in your Activity, and then call view.setBackground(drawable) in onCreate(), after screen rotate, a new Activity instance will be created and the old Activity instance can never be de-allocated because drawable has set the view as callback and view has a reference to Activity (Context). A leaked Activity instance means a significant amount of memory, which will cause OOM easily.

  4. There are two ways to avoid this kind of leakage:

    • Do not keep long-lived references to a context-activity. A reference to an activity should have the same life cycle as the activity itself.
    • Try using the context-application instead of a context-activity.
  5. Be careful about using Threads. Threads in Java are garbage collection roots; that is, the Dalvik Virtual Machine (DVM) keeps hard references to all active threads in the runtime system, and as a result, threads that are left running will never be eligible for garbage collection. Java threads will persist until either they are explicitly closed or the entire process is killed by the Android system. Instead, the Android application framework provides many classes designed to make background threading easier for developers:

    • Use Loader instead of a thread for performing short-lived asynchronous background queries in conjunction with the Activity lifecycle.
    • Use Service and report the results back to the Activity using a BroadcastReceiver.
    • Use AsyncTask for short-lived operations.

How to detect and solve memory leaks issue?

Though, we got introduced with memory leaks, we only need to find the way how to handles this. So how we are going to detect and fix this. Even detecting and fixing a single bug by own is difficult, so you can imagine how difficult is to find and fix memory leaks for the whole app.

Thanks to “The saviour” LeakCanary for saving us from memory leaks problems, it runs along with the application and helps in detecting where the application is leaking memory. It even notify us about where our app is leaking.