十五、HandlerThread的使用和源码

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()
    }

一共分三步:

  1. 开启一个线程
  2. 在run方法里面调用Looper.prepare()
  3. 产生一个Handler对象
  4. 开始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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值