HandlerThread is a class that extends Thread. It means that it is no different from the call of the ordinary Thread class, and it still needs to be called start()
.
As shown in the figure above, the extended HandlerThread class has a Looper and a Handler.
For knowledge about this piece, please refer to "Knowledge we should know about Handler"
The run method of HandlerThread:
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
Calling start()
is to start a thread, and this thread first creates a Looper.
Looper.prepare();
It is to prepare a Looper for the current thread,Looper.myLooper();
It is to retrieve the created Looper.onLooperPrepared();
If you want to set something before running the message queue, you can override this methodLooper.loop();
Run the message queue in this thread
To stop the started Looper, you must call the Looper's quit() method. HandlerThread has such a method:
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
getLooper();
Get the Looper in the HandleThread instancelooper.quit();
End the Looper of the current thread
Having said so much, combined with my last article "Knowledge we should know about Handler", we know that HandlerThread provides a convenience for creating Looper in threads to handle our tasks.
Although there is a getThreadHandler() method in the HandlerThread class to get the Handler, it is impossible for you to call it . This method is @hide
annotated with
/**
* @return a shared {@link Handler} associated with this thread
* @hide
*/
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
@hide It actually controls the android.jar package
Let's talk about that in another article @hide
. Let's continue to talk about HandlerThread.
So we can only create a Handler instance to bind the Looper of the HandlerThread thread:
In this way, our tasks can be placed in other threads for execution. Let's have an example!
val handlerThread = HandlerThread("Hello")
handlerThread.start() // 要在绑定Handler前调用,否则Looper就没有创建好
val handler = object: Handler(handlerThread.looper) {
override fun handleMessage(msg: Message) {
println("Hello world8888888888888888888")
}
}
handler.sendMessage(Message.obtain())
handler.sendMessage(Message.obtain())
Thread.sleep(3000)
handlerThread.quit()// 不再使用的话,要记得停到Looper
// 收到error java.lang.IllegalStateException: Handler ...
// sending message to a Handler on a dead thread
handler.sendMessage(Message.obtain())
For example, we create a thread ourselves and let it start a Looper to help us do things:
var mLooper: Looper? = null
// 启动一个线程,并为当前线程
Thread{
Looper.prepare()
synchronized(this) {
mLooper = Looper.myLooper()
}
Looper.loop()
}.start()
Thread.sleep(3000) // Looper创建是要些时间的,所以我们等一下它。
val myHandler = object: Handler(mLooper!!){
override fun handleMessage(msg: Message) {
println("Hey world @@@@@@@@@")
}
}
myHandler.sendMessage(Message.obtain())
A more elegant version, java's will be simpler:
var mLooper: Looper? = null
val lock = ReentrantLock()
val condition = lock.newCondition()
Thread{
Looper.prepare()
try {
lock.lock()
mLooper = Looper.myLooper()
condition.signalAll()
}catch (e: Exception){
}finally {
lock.unlock()
}
Looper.loop()
}.start()
try {
lock.lock()
if (mLooper == null) condition.await()
}catch (e: Exception){
e.printStackTrace()
}finally {
lock.unlock()
}
val myHandler = object: Handler(mLooper!!){
override fun handleMessage(msg: Message) {
println("Hey world @@@@@@@@@")
}
}
myHandler.sendMessage(Message.obtain())
That's all, thank you for coming!