public class HandlerThread extends Thread { int mPriority; int mTid = -1; Looper mLooper; private @Nullable Handler mHandler; public HandlerThread(String name) { super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } /** * Constructs a HandlerThread. * @param name * @param priority The priority to run the thread at. The value supplied must be from * {@link android.os.Process} and not from java.lang.Thread. */ public HandlerThread(String name, int priority) { super(name); mPriority = priority; } /** * Call back method that can be explicitly overridden if needed to execute some * setup before Looper loops. */ protected void onLooperPrepared() { } @Override public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; } /** * This method returns the Looper associated with this thread. If this thread not been started * or for any reason isAlive() returns false, this method will return null. If this thread * has been started, this method will block until the looper has been initialized. * @return The looper. */ public Looper getLooper() { if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; } /** * @return a shared {@link Handler} associated with this thread * @hide */ @NonNull public Handler getThreadHandler() { if (mHandler == null) { mHandler = new Handler(getLooper()); } return mHandler; }
The key is these. Obviously, the handlerThread encapsulates the looper and handler in a sub thread, so that's why the handlerThread can be used to run directly in the sub thread.
In getLooper, handlethread makes a judgment on whether a thread exists. Because the handler is in the main thread and the Looper created by handlethread is in the sub thread. If the sub thread is not created or the Looper of the sub thread is not created, the handler does not know who to send the message to. So here, the handlerThread adds a layer of judgment to ensure that the Looper of the sub thread is created.
For the use scenario of handlerThread, it is generally used in the sub thread, because if the normal handler is used, you need to create a new Looper in the sub thread (since the main thread already has a Looper by default, you can directly use the handler in the main thread). For example, the handlerThread can be used when the sub thread constantly obtains the data update UI.