记录:Handler、HandlerThread

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010987039/article/details/85765148

记录:Handler、HandlerThread

Handler

相关类

  • Looper: 一个线程可以产生一个 Looper 对象,由它来管理此线程里的 MessageQueue( 消息队列 )和对消息进行循环。
  • Handler: 你可以构造 Handler 对象来与 Looper 沟通,以便 push 新消息到 MessageQueue 里 ; 或者接收 Looper 从 MessageQueue 取出 所送来的消息。
  • Message Queue( 消息队列 ): 用来存放线程放入的消息。
  • Message:是线程间通讯的消息载体。两个码头之间运输货物,Message充当集装箱的功能,里面可以存放任何你想传递的消息。

关系

  • 一个Thread对应多个Handler,一个Thread对应一个Looper和MessageQueue
  • Handler与Thread共享Looper和MessageQueue
  • Message只是消息的载体,将会被发送到与线程绑定的唯一的MessageQueue中,并且被与线程绑定的唯一的Looper分发,被与其自身绑定的Handler消费。

调用流程

  1. 当我们调用handler.sendMessage(msg)方法发送一个Message时,实际上这个Message是发送到与当前线程绑定的一个MessageQueue中
  2. 然后与当前线程绑定的Looper将会不断的从MessageQueue中取出新的Message
  3. 调用msg.target.dispathMessage(msg)方法将消息分发到与Message绑定的handler.handleMessage()方法中。

HandlerThread

在线程(Thread)中,默认是没有Looper,需要手动添加。
官方提供HandlerThread类,方便创建一个拥有Looger实例的线程,结合Handler在子线程中执行耗时或延时等任务。

Handy class for starting a new thread that has a looper. 
The looper can then be used to create handler classes. 
Note that start() must still be called.

特点

  • HandlerThread本质上是一个线程类,它继承了Thread
  • 拥有自己的消息队列,它不会干扰或阻塞UI线程
  • 拥有自己的内部Looper对象,可以进行looper循环
  • 通过获取HandlerThread的looper对象传递给Handler对象,可以在handleMessage方法中执行异步任务
  • 创建HandlerThread后必须先调用HandlerThread.start()方法,Thread会先调用run方法,创建Looper对象。

使用

class MainActivity : AppCompatActivity() {

    private lateinit var handlerThread: HandlerThread
    private lateinit var handler: Handler

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        handlerThread = HandlerThread(javaClass.simpleName)
        handlerThread.start()
        handler = Handler(handlerThread.looper) {
            //处理消息
            true
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        handler.removeCallbacksAndMessages(null)
        handlerThread.quit()
    }
}

退出循环

HandlerThread提供两个方法退出循环。

quit

将不在接受新的事件加入消息队列
清空MessageQueue中所有消息,无论是否是延迟消息

quitSafely

将不在接受新的事件加入消息队列
清空MessageQueue中所有的延时消息
API 18 引入
区别:清空消息之前会派发所有的非延迟消息

 /**
     * Quits the looper.
     * <p>
     * Causes the {@link #loop} method to terminate without processing any
     * more messages in the message queue.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p><p class="note">
     * Using this method may be unsafe because some messages may not be delivered
     * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure
     * that all pending work is completed in an orderly manner.
     * </p>
     *
     * @see #quitSafely
     */
    public void quit() {
        mQueue.quit(false);
    }

    /**
     * Quits the looper safely.
     * <p>
     * Causes the {@link #loop} method to terminate as soon as all remaining messages
     * in the message queue that are already due to be delivered have been handled.
     * However pending delayed messages with due times in the future will not be
     * delivered before the loop terminates.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p>
     */
    public void quitSafely() {
        mQueue.quit(true);
    }

猜你喜欢

转载自blog.csdn.net/u010987039/article/details/85765148
今日推荐