Android異步消息傳遞機制

Handler的異步消息傳遞機制

MessageQueue工作原理

  • MessageQueue主要包含兩個操作:插入和讀取。讀取操作本身會伴隨着刪除操作,插入和讀取對應的方法分別爲enqueueMessage和next,其中enqueueMessage的作用是往消息隊列中插入一條消息,而next的作用是從消息隊列中取出一條消息並將其從消息隊列中移除。儘管MessageQueue叫消息隊列,但是它的內部實現並不是用的隊列,實際上它是通過一個單鏈表的數據結構來維護消息列表,單鏈表在插入和刪除上比較有優勢。
  1. enqueueMessage方法的主要操作其實就是單鏈表的插入操作。
  2. next方法是一個無限循環的方法,如果消息隊列中沒有消息,那麼next方法會一直阻塞在這裏。當有新消息到來時,next方法會返回這條消息並將其從單鏈表中移除。
    在這裏插入圖片描述
    在這裏插入圖片描述

Looper工作原理

  • Looper在Android的消息機制中扮演着消息循環的角色,具體來說就是它會不停地從MessageQueue中查看是否有新消息,如果有新消息就會立刻處理,否則就一直阻塞在那裏。
  • 在構造方法中它會創建一個MessageQueue,即消息隊列,然後將當前線程的對象保存起來。
    在這裏插入圖片描述
  • 通過Looper.prepare,即可爲當前線程創建一個Looper,接着通過Looper.loop()來開啓消息循環,Looper除了prepare方法外,還提供了prepareMainLooper方法,這個方法主要是給主線程也就是ActivityThread創建Looper使用的,其本質也是通過prepare方法來實現的。由於主線程的Looper比較特殊,所以Looper提供了一個getMainLooper方法,通過它可以在任何地方獲取到主線程的Looper。
  • Looper也是可以退出的,Looper提供了quit和quitSafely來退岀一個Looper,二者的區別是:quit會直接退出Looper,而quitSafely只是設定一個退出標記,然後把消息隊列中的已有消息處理完畢後才安全地退出。在子線程中,如果手動爲其創建了Looper,那麼在所有的事情完成以後應該調用quit方法來終止消息循環,否則這個子線程就會一直處於等待的狀態,而如果退出Looper以後,這個線程就會立刻終止。
  • loop方法是一個死循環,唯一跳岀循環的方式是MessageQueue的next方法返回了null。當Looper的quit方法被調用時,Looper就會調用MessageQueue的quit或者quitSafely方法來通知消息隊列退出,當消息隊列被標記爲退出狀態時,它的next方法就會返回null。也就是說,Looper必須退出,否則loop方法就會無限循環下去。loop方法會調用MessageQueue的next方法來獲取新消息,而next是一個阻塞操作,當沒有消息時,next方法會一直阻塞在那裏,這也導致loop方法一直阻塞在那裏。如果MessageQueue的next方法返回了新消息,Looper就會通過msg.target.dispatchMessage(msg)處理這條消息,這裏的msg.target是發送這條消息的Handler對象,這樣Handler發送的消息最終又交給它的dispatchMessage方法來處理了。但是這裏不同的是,Handler的dispatchMessage方法是在創建Handler時所使用的Looper中執行的,這樣就成功地將代碼邏輯切換到指定的線程中去執行了。
    [image:0551119B-2F44-456D-811E-EE2D279CEE11-547-00000B99E7F80D08/C0F72944-7C71-4C73-81CB-85639F5699B6.png]

Handler工作原理

  • Handler工作主要包含消息的發送和接收過程。
  • 消息的發送可以通過post的一系列方法以及send的一系列方法來實現,post的一系列方法最終是通過send的一系列方法來實現的。
    在這裏插入圖片描述
  • Handler發送消息的過程僅僅是向消息隊列中插入了一條消息,MessageQueue的next方法就會返回這條消息給Looper,Looper收到消息後就開始處理了,最終消息由Looper交由Handler處理,即Handler的dispatchMessage方法會被調用,這時Handler就進入了處理消息的階段。


    首先,檢查Message的callback是否爲null,不爲null就通過handleCallback來處理消息。Message的callback是一個Runnable對象,實際上就是Handler的post方法所傳遞的Runnable參數。其次,檢査mCallback是否爲null,不爲null就調用mCallback的handleMessage方法來處理消息。Callback是個接口。通過Callback可以採用如下方式來創建Handler對象:Handler handler=new Handler(callback)。Callback可以用來創建一個Handler的實例但並不需要派生Handler的子類。在日常開發中,創建Handler最常見的方式就是派生一個Handler的子類並重寫其handleMessage方法來處理具體的消息,而Callback給我們提供了另外一種使用Handler的方式,當我們不想派生子類時,就可以通過Callback來實現。最後,調用Handler的handleMessage方法來處理消息。
  • Handler還有一個特殊的構造方法,那就是通過一個特定的Looper來構造Handler,通過這個構造方法可以實現一些特殊的功能。
  • Handler的默認構造方法會調用下面的構造方法,很明顯,如果當前線程沒有Looper的話,就會拋出異常,這也解釋了在沒有Looper的子線程中創建Handler會引發程序異常的原因。
    [image:CD12A8EB-247F-4D84-8B8C-28EAAFAB83D8-547-00000CE809FD55BC/58BF6441-AF2D-4C7F-9D8B-D83AA61CE946.png]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章