Handlers [Memory Leaks]

This post is part continuation of Memory Leaks in Android

Handler is also one of the choice, when we want to commnicate between any thread and Android’s main UI Thread. It is not so hard to use, little complex one when compared to AsyncTask, but offers more flexibilty as well. Below is excerpt from developer.android.com

A Handler allows you to send and process Message and Runnable objects associated with a thread’s MessageQueue. Each Handler instance is associated with a single thread and that thread’s message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it — from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.

Lets takes similar example which we discussed in AsyncTask [Memory leaks], Similar implementation using Thread and Handler can be done as below

private void updateProgressUsingThread() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < AppConstants.LOOP_COUNT; i++) {
                    try {
                        Thread.sleep(AppConstants.THREAD_SLEEP_TIME);
                        progressCount++;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    publishProgress(progressCount);
                }
        }
    }).start();
}

Problem:

You can see in below gif, how this perfectly looking code snippet is causing memory leak, Which is getting detected via awesome LeakCanary lib.

LeakyHandler

 

Now it not so hard to guess what happened, as we have similar issue with AsyncTask implementation,as we pressed back button, activity gets destroyed. But background Thread continues to run and it holds reference to our activity.

Solution:

Now we are going to miss AsyncTask cancel() method, unfortunately we don’t have any such method of Thread class. 😦

No need to worry, we developers are very good at borrowing GOOD things from various places 🙂 We can have our own flag to tell whether background thread was canceled or not, and use that to mimic AsyncTask solution here. Here is updated code snippet

private boolean isCanceled = false;

private void updateProgressUsingThread() {
    mThread=new Thread(new Runnable() {
        @Override
        public void run() {
                for (int i = 0; i < AppConstants.LOOP_COUNT; i++) {
                    if(!isCanceled) {
                        try {
                        Thread.sleep(AppConstants.THREAD_SLEEP_TIME);
                        progressCount++;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    publishProgress(progressCount);
                }
            }
        }
    });
    mThread.start();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    isCanceled=true;
    mHander.removeCallbacksAndMessages(null);
}

And here is GIF with solution applied:)

Handler

 

So here LeakCanary didn’t detected any memory leak again, Awesome:) isn’t it ?

AsyncTask [Memory leaks]

This post is part continuation of Memory Leaks in Android

For any work which needs to be done of UI thread, we do have many choices for that AsyncTask is one of them. Its pretty straight forward to use. Below is excerpt from developer.android.com

AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask.

An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground, onProgressUpdate andonPostExecute.

But if we do not use it proper way, it can cause memory leaks in app. Consider below example.

private void updateProgressAsyncTask() {
    mProgressAsyncTask=new AsyncTask<Void, Integer, Void>() {
        @Override
        protected Void doInBackground(Void... voids) {
            for (int i = 0; i < AppConstants.LOOP_COUNT; i++) {
                    try {
                        Thread.sleep(AppConstants.THREAD_SLEEP_TIME);
                        progressCount++;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    publishProgress(progressCount);
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            updateCounter(values[0]);
        }
    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}

 

Problem:

You can see in below gif, how this perfectly looking AsyncTask is causing memory leak, Which is getting detected via awesome LeakCanary lib.

leakyAsyncTask

Wondering, how it happened ? Its simple that as soon as we pressed back button, activity gets destroyed. But AsyncTask continues to run and it holds reference to our activity.

Solution:

its not hard, just remember to cancel AsyncTask in activity’s onDestory() method. Though there is one catch that AsyncTask’s cancel() method doesn’t stop and can’t stop the running background thread itself, though it can help you stop processing background thread. cancel() method does set a flag, using which you can stop processing in background thread. Here is updated code snippet

private void updateProgressAsyncTask() {
    mProgressAsyncTask=new AsyncTask<Void, Integer, Void>() {
        @Override
        protected Void doInBackground(Void... voids) {
            for (int i = 0; i < AppConstants.LOOP_COUNT; i++) {
                if (!isCancelled()) {//check that if canceled or not
                    try {
                        Thread.sleep(AppConstants.THREAD_SLEEP_TIME);
                        progressCount++;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    publishProgress(progressCount);
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            updateCounter(values[0]);
        }
    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if(mProgressAsyncTask!=null)//cancel asynctask
        mProgressAsyncTask.cancel(true);
}

 

And here is GIF with solution applied:)

AsyncTask

 

So here LeakCanary didn’t detected any memory leak, Awesome:) isn’t it ?

 

 

Memory Leaks in Android

In this series, we will cover often ignored aspect of Android app development, Memory Leaks

What is memory leak?

Android is managed memory environment, As a developer you don’t need to take care of allocating, deallocating memory yourself, Garbage Collector takes care of freeing up objects that are no longer needed. But GC can’t free up objects which are still getting referenced, it results in precious memory not getting freed. This non freed objects are called leaks.

How to find memory leaks

This is not a trivial problem to solve :(, what you can’t see with your eyes, is something you won’t be able to find easily.

Hard Way

Using MAT(Memory analyser tool) we can do this, it requires lots of steps and patience.

  1. Take heap dump using DDMS hprof dump.
  2. Convert in to format which MAT can understand
  3. Open converted dump in MAT
  4. Analyse denominator tree,leak suspects to find out root cause of leaks.

The Eclipse Memory Analyzer is a fast and feature-rich Java heap analyzer that helps you find memory leaks and reduce memory consumption.

Use the Memory Analyzer to analyze productive heap dumps with hundreds of millions of objects, quickly calculate the retained sizes of objects, see who is preventing the Garbage Collector from collecting objects, run a report to automatically extract leak suspects.

Easy way

Use Leakcanary, awesome library from square is here to rescue you.

A memory leak detection library for Android and Java.

“A small leak will sink a great ship.” – Benjamin Franklin

It does most of the stuff mentioned in Hard Way itself for you, And now you can SEE leaks too….yay

Screen Shot 2016-08-22 at 11.07.12 PM

Setup instructions can be found here

We will cover common mistakes with examples & how to fix them in future posts.