Picture

Hi, I'm Stephen Nicholas.

And this is my blog. I'm a software engineer by trade (but mostly for fun) with a wide variety of experience and interests. Some of which I'll write about here.

How to use the Android HandlerThread

Today I’m going to talk about something I ran into recently that turned out to be very simple, despite initially seeming a little confusing, the Android HandlerThread class.

So, first of all, why did I run into this? Well, basically I’ve been doing some work to improve the multi-threading of one of my applications, by splitting off some of the background work into a number of different threads; and to allow those threads to be easily interacted with, I wanted each of them to have their own Handler.

Now I’d read how to turn a thread into a Handler thread by calling Looper.prepare(), setting up my Handler & then calling Looper.loop(); however this left my thread unable to perform its own background activities and so I ended up creating sub-threads / runnables and things started getting rather messy.

Assuming there must be a better way to do this, I eventually came across HandlerThread, which is described in the Android documentation as:

Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.

Now, in retrospect that actually seems quite clear- so I’m hoping that by writing this post, I’m not just exposing my stupidity- but initially I was a little unsure what it meant and how to use it.

Anyway, long story short, after some searching and some experimentation, I came across the correct way to use it. Which is, unsurprisingly, very similar to how it’s described above:

First of all you create and start a HandlerThread, which creates a thread with a Looper:

//Create and start the handler thread & give it a custom name  
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");  
handlerThread.start();  

You then get the Looper from the HandlerThread as follows:

  
//Get the looper from the handlerThread  
Looper looper = handlerThread.getLooper();  

Note that the above method call can return null, in the unlikely event that the HandlerThread not been started or if for any reason isAlive() returns false. Practically I think this is unlikely to happen and I’m not sure if there’s anything sensible to do if it does, so I wouldn’t worry about it too much.

You can then create your Handler, passing in the Looper for it to use

  
//Create a new handler- passing in the looper for it to use  
Handler handler = new Handler(looper);  

And that’s all there is to it. You’ve now you got your own Handler running in it’s own thread. Simple, right?

And finally, when your thread is finished, you can shut down the HandlerThread as follows:

  
//Shut down the HandlerThread  
handlerThread.quit();  

Just for completeness, below is an example of a complete class that extends thread and uses a HandlerThread to create a Handler for inter-thread communication. As a side note, it also demonstrates the use of the Handler.Callback interface to save you having to subclass Handler for performing your custom message handling.

  
package com.stephendnicholas;

import android.os.Handler;  
import android.os.Handler.Callback;  
import android.os.HandlerThread;  
import android.os.Looper;  
import android.os.Message;

public class ExampleThread extends Thread implements Callback {

  public static final int CUSTOM_MESSAGE = 1;

  private boolean running = true;

  private final Object mutex = new Object();

  public ExampleThread() {  
  }

  @Override  
  public void run() {  
    // Create and start the HandlerThread- it requires a custom name  
    HandlerThread handlerThread = new HandlerThread("MyHandlerThread");  
    handlerThread.start();

    // Get the looper from the handlerThread  
    // Note: this may return null  
    Looper looper = handlerThread.getLooper();

    // Create a new handler- passing in the looper to use and this class as  
    // the message handler  
    Handler handler = new Handler(looper, this);

    // While this thread is running  
    while (running) {

      // TODO- custom thread logic

      // Wait on mutex  
      synchronized (mutex) {  
        try {  
          mutex.wait();  
        } catch (InterruptedException e) {  
          // Don't care  
        }  
      }  
    }

    // Tell the handler thread to quit  
    handlerThread.quit();  
  }

  public void shutdown() {  
    // Set running to false  
    running = false;

    // Wake anyone waiting on mutex  
    synchronized (mutex) {  
      mutex.notifyAll();  
    }  
  }

  @Override  
  public boolean handleMessage(Message msg) {

    switch (msg.what) {  
      case CUSTOM_MESSAGE:  
      // TODO- custom logic  
      break;

      default:  
      // Return false- as we have not handled the message  
      return false;  
    }

    // Return true- as we have handled the message  
    return true;  
  }

}