In previous parts, we've delved into Handler, Looper and Message, understanding their roles in enabling code execution within a specified thread and facilitating safe communication between threads.
The HandlerThread class combines these concepts, simplifying the acquisition of Looper and Handler objects. In this article, we'll explore the implementation of HandlerThread referencing some AOSP code examples.
Internals of HandlerThread
HandlerThread extends the Thread class, providing additional functionality for initializing a Looper and Handler for the associated thread.
Here's the class definition:
public class HandlerThread extends Thread {
}
UML class diagram of HandlerThread is shown below:

As demonstrated, HandlerThread essentially functions as a regular Java thread with added capabilities for constructing Looper and providing access to the Looper and Handler instances.
Recap: Construction of Looper
Examining the run() method of HandlerThread, we observe the process of Looper initialization, as discussed in first article of this series.
Looper.prepare() will create a new instance and can be called only once inside a Thread. Looper.loop() waits for message to appear in MessageQueue and process them. For detailed information and innerworking of this, I suggest to read this article.
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
Uses of HandlerThread
Now that we understand what HandlerThread is and how it operates, let's explore its practical utility.
Example1: Setting's App - WifiDialogActivity.java
In this example, HandlerThread is used to obtain a Handler object for the underlying Thread.
View Full Code Here.
if (mIsWifiTrackerLib) {
mWorkerThread = new HandlerThread(
TAG + "{" + Integer.toHexString(System.identityHashCode(this)) + "}",
Process.THREAD_PRIORITY_BACKGROUND);
mWorkerThread.start();
mNetworkDetailsTracker = FeatureFactory.getFactory(this)
.getWifiTrackerLibProvider()
.createNetworkDetailsTracker(
getLifecycle(),
this,
new Handler(Looper.getMainLooper()),
mWorkerThread.getThreadHandler(),
elapsedRealtimeClock,
MAX_SCAN_AGE_MILLIS,
SCAN_INTERVAL_MILLIS,
mIntent.getStringExtra(KEY_CHOSEN_WIFIENTRY_KEY));
}
Example 2: Camera2 App - CaptureModule.java
Here, HandlerThread is utilized to acquire a Looper for creating a new Handler object.View Full Code Here.
@Override
public void init(CameraActivity activity, boolean isSecureCamera, boolean isCaptureIntent) {
HandlerThread thread = new HandlerThread("CaptureModule.mCameraHandler");
thread.start();
mCameraHandler = new Handler(thread.getLooper());
}
Conclusion
HandlerThread simplifies the creation of a Looper, which otherwise would require manually extending Thread class and overloading the run() method with similar implementation. Understanding the functionality of HandlerThread equips us to leverage its benefits in our projects effectively.
In the next article, we'll address potential memory leak issues with Handler and how to mitigate them.
If you find these articles helpful, please consider liking or commenting to support future content. If you have any questions or topics you'd like covered, feel free to leave a comment below.