Android Loopers and Handlers: The Journey to Implement a Worker Thread.

Masoud Fallahpour
5 min readJan 5, 2022
Photo by amirali mirhashemian on Unsplash

In this post, I’m going to talk about Loopers and Handlers in Android. Hopefully, after reading this post you’ll know when and how to use them.

In order to get to know Loopers and Handlers, we are going to implement a worker thread but before that let’s get familiar with the Thread class.

Thread

Java/Kotlin has a class named Thread which is used to execute some code off the main thread. To use the Thread class we need to do 3 things:

  • Create a new class inheriting from Thread
  • Override the run method
  • Create a new instance of our class and call its start method

This is how it’s done in code:

After calling start the execution of the thread starts.

One important note about MyThread is that as soon as run is finished, the thread is destroyed.

Now suppose that we don't want our thread to be destroyed when it is done. In other words, when the thread is done with its current task, instead of being destroyed, it waits until another task is available for execution. Basically, we want to have a worker thread.

Worker Thread

A worker thread has a queue of tasks. When the thread is finished with its current task it picks the next task from the queue and executes it. When the queue of tasks is empty then the thread keeps waiting until a task is available to execute.

What we’re going to do is to implement a worker thread in three different ways. From the most cumbersome to the most elegant!

Handcrafted Worker Thread

In order to implement a worker thread from scratch, using the Thread class, we need to do a couple of things:

  • Putting an infinite loop inside the run method
  • Creating a queue for keeping track of the tasks to execute
  • Inside the infinite loop, we get the next task from the queue and execute it
  • Find a way to break out of that infinite loop so that we can stop the worker thread when we are done.

The following code does all of the above.

To add a task to the queue of the worker thread we call execute. Calling quit finishes the worker thread. We can use the HandcraftedWorkerThread like the following.

Our worker thread works but it has two problems:

  1. When there is no task to execute, the while loop inside the run method is constantly checking the value of isAlive. This is busy waiting and as we all know we are wasting CPU cycles.
  2. We are doing too much work to implement a worker thread! Actually not too much really but we can avoid things like managing the queue of tasks ourselves.

Now it’s time for a better implementation of a worker thread.

Looper Worker Thread

Before implementing the second version of our worker thread we need to get familiar with two classes.

Looper

Looper class does two things:

  1. It converts an ordinary thread (which is destroyed when its run method is finished) to a thread that can stay alive as long as the Android app is alive.
  2. It has a queue of tasks to execute.

Handler

We can not directly add a task to the queue of a Looper. Instead, we should use an instance of a Handler to do the trick. In other words, we use a Handler to add a task to the queue of a Looper.

Now we can implement the second version of our worker thread using a Looper and a Handler.

A couple of notes about the above implementation:

  • To convert an ordinary thread to a thread that can run forever we need to call Looper.prepare() and then Looper.loop(). Also, prepare should always be called after the start method of the thread. Otherwise, it will throw an exception.
  • To communicate with the queue of the Looper we have created an instance of Handler and passed the Looper of the current thread to the Handler.
  • To add a task to the queue of the Looper we call Handler.post() and pass it a Runnable.
  • When we are done with the worker thread we should call the quit method to stop its associated Looper.

We can use the LooperWorkerThread just like how we did with the HandcraftedWorkerThread.

With this implementation, we eliminated the busy waiting and also got rid of manually managing the queue of tasks.

We can still do better than this! Here is how.

Handler Worker Thread

To create a worker thread we can inherit from HandlerThread instead Thread. This makes things a lot easier. The reason is that HandlerThread has an inner Looper so we don't need to create one manually.

What follows is the implementation of a worker thread using a HandlerThread.

Some notes about the code above:

  • As stated earlier, because HandlerThread has an inner Looper there is no need to create one explicitly.
  • To communicate with the Looper of HandlerThread we have created a Handler. Note that when we create an instance of Handler without passing a Looper to its constructor, the Handler implicitly uses the Looper of the current thread. Here, the Handler will be associated with the Looper of the HandlerThread.
  • We do a check inside execute to make sure that handler is initialized before calling its post method. The reason is that this way we prevent a runtime error if, by any chance, execute is called before onLooperPrepared callback is called.
  • We have created the Handler inside the onLooperPrepared method. The reason is that we should create the Handler only when the Looper is prepared. When the Looper of HandlerThread is prepared the onLooperPrepared is called and that’s where we instantiate the Handler.

And this is it. Just compare HandlerWorkerThread with HandcraftedWorkerThread to appreciate what we achieved!

The Main Thread of an Android App

Now that we know about Loopers and Handlers we can talk a little bit about the main thread of an Android app. This thread is also called the UI thread as well.

Each Android app has a single main thread. The main duty of this thread is handling the user’s interactions with the app like clicking a button, rendering a list of items, and so on.

Suppose that the main thread is an ordinary thread. One that gets destroyed when its run method is finished. The user starts the app, the main thread starts executing, the UI of the first screen of the app is displayed and the main thread is destroyed!

Does that sound weird? Yes! Because that’s not what happens in reality. What actually happens is that the main thread is alive as long as the app is alive. So the main thread of an Android app is not an ordinary thread. It’s a worker thread. You see, it’s a worker thread!

Because the main thread of an Android app is a worker thread that means it has a Looper associated with it and there is a queue of tasks. All interactions of the user with the app like clicking a button, scrolling a list, and so on are added as a task to the queue of the main thread and are executed one by one.

Congrats! By now you should have a good grasp of Loopers, Handlers, and worker threads.

You can access the source code of this post from the following link.

--

--

Masoud Fallahpour

Software engineering @ Klarna. Software engineer, *nix lover, curious learner, gym guy, casual gamer.