HandlerThread我们都知道是用来在子线程使用Handler的,那我们来看看,如果不用HandlerThread,我们怎么在子线程使用Handler呢?
示例代码片段:
自定义Thread开启Handler
fun startHandlerWithThread() {
Thread {
Looper.prepare()
mCustomThreadHandler = object : Handler(Looper.myLooper()!!) {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
Log.d(TAG,"mCustomThreadHandler handleMsg = >"+msg.what)
}
}
Looper.loop()
}.start()
}
一共分三步:
- 开启一个线程
- 在run方法里面调用Looper.prepare()
- 产生一个Handler对象
- 开始loop()
Looper.prepare()
这个函数里面做了什么呢?我们点进去看看:
Looper.java
public static void prepare() {
prepare(true);
}
|
\|/
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
源码还是比较简单的,就是new了一个Looper.放到ThreadLocal里面,如果你下次还调用prepare就会给你抛出RuntimeException异常。默认是quitAllowed的。
Looper.loop()
public static void loop() {
final Looper me = myLooper();
me.mInLoop = true;
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// Make sure the observer won't change while processing a transaction.
msg.target.dispatchMessage(msg);
msg.recycleUnchecked();
}
}
可以看到,这里面主要还是派发消息。就是开启派发消息的逻辑。到这里Handler就算起来了。那HandlerThread是怎么做的呢?
HandlerThread
fun startHandlerWithHandlerThread() {
var handlerThread = HandlerThread("handlerThread")
handlerThread.start()
mThreadHandler =object :Handler(handlerThread.looper){
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
Log.d(TAG,"mCustomThreadHandler handleMsg = >"+msg.what)
}
}
}
可以看到,使用HandlerThread更简单,我们不用显示的开启子线程,直接获取线程的looper给handler就可以了。那么它内部做了什么呢,我们可以先看看继承关系与构造函数:
public class HandlerThread extends Thread {
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
}
继承自Thread,构造函数会设置默认的线程优先级,接下来看看run函数:
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
到这里是不是有熟悉的味道?这里其实就和我们前面在子线程产生Looper是一样的逻辑。HandlerThread主要的逻辑就是把子线程产生Looper的逻辑进行了一层封装。
退出Looper
mThreadHandler?.looper?.quit()
mThreadHandler?.looper?.quitSafely() -> quit(true)
其实就这简单的一句代码,那么退出Looper都做什么了?退出后消息是怎么处理的?
MessageQueue.java
void quit(boolean safe) {
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) {
return;
}
mQuitting = true;
if (safe) {
removeAllFutureMessagesLocked();
} else {
removeAllMessagesLocked();
}
// We can assume mPtr != 0 because mQuitting was previously false.
nativeWake(mPtr);
}
}
退出后,明显可以看到是,设置了一个标记为,先标记为退出状态了,然后根据是否safe来调用对应的移除消息方法:
先看看safe = false时的removeAllMessagesLocked();
private void removeAllMessagesLocked() {
Message p = mMessages;
while (p != null) {
Message n = p.next;
p.recycleUnchecked();
p = n;
}
mMessages = null;
}
可以看出就是循环把下一个消息清除掉。那我们来看看safe = true的情况removeAllFutureMessagesLocked():
private void removeAllFutureMessagesLocked() {
final long now = SystemClock.uptimeMillis();
Message p = mMessages; //当前正在处理的message
if (p != null) {
if (p.when > now) { //延时消息,因为when大于现在的时间
removeAllMessagesLocked();//清除p后面链表的所有消息,时间大于p.when
} else {
//寻找链表里面有无when大于now的
Message n;
for (;;) {
n = p.next;
if (n == null) {
return;
}
//找到了,跳出循环
if (n.when > now) {
break;
}
//没找到往下一个节点走
p = n;
}
//断开p后面的链子
p.next = null;
do {
p = n;
n = p.next;
p.recycleUnchecked();
} while (n != null); //n后面的所有节点都要回收
}
}
}
到这里退出就讲完了
最后在这里贴一段HandlerThread的实例代码:
package com.jhzl.handlerthread
import android.os.*
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import android.widget.Button
class HandlerThreadActivity : AppCompatActivity() {
private val TAG = "HandlerThreadActivity"
private var mCustomThreadHandler: Handler? = null
private var mThreadHandler: Handler? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_handler_thread)
findViewById<Button>(R.id.start_thread_btn).setOnClickListener {
startHandlerWithThread()
}
findViewById<Button>(R.id.start_handler_thread_btn).setOnClickListener {
startHandlerWithHandlerThread()
}
findViewById<Button>(R.id.quit_custom_handler_btn).setOnClickListener {
mCustomThreadHandler?.looper?.quit()
}
findViewById<Button>(R.id.send_message_custom_btn).setOnClickListener {
mCustomThreadHandler?.sendEmptyMessage(12)
}
findViewById<Button>(R.id.send_message_standard_btn).setOnClickListener {
mThreadHandler?.sendEmptyMessage(11)
}
findViewById<Button>(R.id.quit_standard_handler_btn).setOnClickListener {
mThreadHandler?.looper?.quit()
}
}
fun startHandlerWithThread() {
Thread {
Looper.prepare()
mCustomThreadHandler = object : Handler(Looper.myLooper()!!) {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
Log.d(TAG,"mCustomThreadHandler handleMsg = >"+msg.what)
}
}
Looper.loop()
}.start()
}
fun startHandlerWithHandlerThread() {
var handlerThread = HandlerThread("handlerThread")
handlerThread.start()
mThreadHandler =object :Handler(handlerThread.looper){
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
Log.d(TAG,"mCustomThreadHandler handleMsg = >"+msg.what)
}
}
}
}
源代码例子:https://github.com/JHknowlege/HandlerThread