HandlerThreads and why you should be using them in your Android apps

I first came across HandlerThread while peering through some code for Android. I got curious as to what it did and looked up the code. It is an extension of Thread, which works with a Looper. Meaning, it is meant to handle multiple jobs on the background thread.

Ali Muzaffar
5 min readNov 24, 2015

--

This was my first and last encounter with them for a while. It seemed like a very low level API and something that may not necessarily be meant to be used by app developers. I had rarely (almost never) seen it used in any code sample for how to do perform asynchronous tasks in Android. I did mentioned them as a way to do asynchronous processing in my article 8 ways to do asynchronous processing in Android and counting, even there, I deferred to just regular Theads and ignored how HandlerThreads are used.

It wasn't till a recent conversation with Colt McAnlis at the BABBQ15 that I heard the mentions of HandlerThreads again. The difference this time was that they were in context of how they process commands from a queue and how this makes for situations where you have to perform a lot of asynchronous tasks. This sounded like just about every application I have written, so why weren't these mentioned more readily in Android Development literature?

Since the BABBQ, I’ve looked some into HandlerThreads and from what I figure, there are 2 main reasons why developers/educators may be inclined to not mention HandlerThreads.

  1. HandlerThreads run outside of your activity’s lifecycle, so they need to be cleaned up properly or else you will have thread leaks. This is especially dangerous if you are using them for long running processes. I recall Colt mentioning (I may be wrong) that you can have HandlerThreads with a timeout, so if they haven’t processed anything from the queue in a while, they should terminate themselves. I haven’t been able to find any way of doing this, short of extending HandlerThreads and adding the functionality myself. Update: HandlerThread doesn’t have a time out, a ThreadpoolExecutor has a timeout that can be used to wind down unused threads.
  2. There is no convenient mechanism for posting results back to the main thread. This means more boilerplate code.

What is the problem with AsyncTask

AsyncTasks have a single thread dedicated to them, so if you spin off more than one AsyncTask, they aren’t truly asynchronous. This is not necessarily a problem, but it is restrictive if you do want multiple threads. With each AsyncTask that is spun off, a thread is created and destroyed which, if you have a lot of AsyncTasks is a performance issue.

What is wrong with Service

Services are executed on the main thread, so they aren't really asynchronous. You have to create a separate thread for them to use if you want them to be asynchronous. With both of these you still have a new thread being created and destroyed.

Why not use IntentService

As Ian Lake points out (link to discussion on Google+), IntentService does use HandlerThread internally (link to source) and this does make them a great option to use. He also points out that there is ever only one instance of a Service in existence at any given time and it has only one HandlerThread. This means that if you need more than one thing to happen at the same time, IntentServices may not be a good option. However, looking at the source for the IntentService, it does illustrate that the techniques discussed below are in fact used within the Android SDK itself and as such it is a design pattern you should be familiar with.

How do I use HandlerThreads

There are 2 main ways that I found to use HandlerThreads.

  1. Create a new HandlerThread, create a new Handler using this HandlerThread and post your tasks on this handler.
  2. Extend HandlerThread inside your CustomHandlerThread, create a Handler to process your task. You would take this approach if you know the task you want to perform and just need to pass in parameters. An example would be creating a HandlerThread to download images or perform networking operations.

Implementation of HandlerThread

The implementation is very straight forward.

HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
Looper looper = handlerThread.getLooper();
Handler handler = new Handler(looper);

As I mentioned earlier, we create a new HandlerThread and give it any name. We then start the HandlerThread, get the Looper for the HandlerThread and pass it to a handler.

Then, in order to use it, you simply have to post Runnable to the Handler thread.

handler.post(new Runnable(){…});

If you have a few different tasks you would like to perform on the background thread, it may be a better idea to extend handler and adding handling for different messages. Note, there is still one background thread here. If you want more threads, you’ll have to create more Handlers and HandlerThreads.

if (mHandler == null) {
mHandler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SOMETHING_ACTION: {
doSomething();
break;
}
case SOMETHING_ELSE_ACTION:
doMoreThings();
break;
default:
break;
}
}
};
}
//usage
mHandler.obtainMessage(SOMETHING_ACTION, "");
mHandler.sendMessage(msg);

IMPORTANT: Remember to call handlerThread.quit() when you are done with the background thread or on your activities onDestroy() method.

As you can see, Option 1 is probably best suited in situations where you don’t have a lot of code. I haven’t covered the scenario of posting back the result to the main thread either.

Posting back the results to the UI thread

There are two approaches that are best used here. You can either make a LocalBroadcast with the result:

Intent in = new Intent(DO_SOMETHING_RESULT);
in.putExtra(DO_SOMETHING_RESULT, result);
LocalBroadcastManager.getInstance(context).sendBroadcast(in);

The great thing about this approach is that you can simply receive the result on the Main thread without having to do anything extra. The down side is that the method is a lot slower than using a callback.

In order to use a callback, you can explicitly get a Handler on the main thread:

Handler mainHandler = new Handler(context.getMainLooper()); 

Runnable myRunnable = new Runnable() {
@Override
public void run() {
MainActivity.this.onResult();
} // This is your code
};
mainHandler.post(myRunnable);

Or, if you are creating the Handler on the main thread, simply calling new Handler() should return a Handler on the main thread.

Implementation of HandlerThreads by creating a custom HandlerThread, is simply a combination of the techniques that I have shown above. There is a great blog post by Nikita that explains how to do this. He also has a great post in which he explain Looper, Handler and HandlerThread and the interaction between them I highly recommend reading this to get a deeper understanding of how Android apps work.

Yay! you made it to the end! We should hang out! feel free to follow me on Medium, LinkedIn, Google+ or Twitter.

--

--

Ali Muzaffar

A software engineer, an Android, and a ray of hope for your darkest code. Residing in Sydney.