記錄: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);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章