承接上一篇handler系列一,上篇主要總結了handler如何通信,這篇來介紹handler怎麼通信。
handler的通信機制
handler,looper,messagequeue如何關聯

建立handler,并采用目前線程的looper建立消息循環系統;
handler通過sendmessage(message)或post(runnable)發送消息,調用enqueuemessage把消息插入到消息連結清單中;
looper循環檢測消息隊列中的消息,若有消息則取出該消息,并調用該消息持有的handler的dispatchmessage方法,回調到建立handler線程中重寫的handlemessage裡執行。
handler及其關聯的類圖
以上類圖可以快速幫助我們理清handler與looper、messagequeue的關系,以下從源碼的角度慢慢分析:
上一段很熟悉的代碼:
從sendmessagequeue開始追蹤,函數調用關系:sendmessage -> sendmessagedelayed ->sendmessageattime,在sendmessageattime中,攜帶者傳來的message與handler的mqueue一起通過enqueuemessage進入隊列了。
對于postrunnable而言,通過post投遞該runnable,調用getpostmessage,通過該runnable構造一個message,再通過 sendmessagedelayed投遞,接下來和sendmessage的流程一樣了。
在enqueuemessage中,通過messagequeue入隊列,并為該message的target指派為目前的handler對象,記住<code>msg.target</code>很重要,之後looper取出該消息時,還需要由<code>msg.target.dispatchmessage</code>回調到該handler中處理消息。
在messagequeue中,由message的消息連結清單進行入隊列
構造looper時,建構消息循環隊列,并擷取目前線程
但該函數是私有的,外界不能直接構造一個looper,而是通過looper.prepare來構造的:
這裡建立looper,并把looper對象儲存在sthreadlocal中,那sthreadlocal是什麼呢?
static final threadlocal sthreadlocal = new threadlocal();
theadlocal 如何儲存與擷取looper?
在<code>loop</code>中,一個循環,通過<code>next</code>取出messagequeue中的消息
若取出的消息為null,則結束循環,傳回。
設定消息為空,可以通過messagequeue的quit和quitsafely方法通知消息隊列退出。
若取出的消息不為空,則通過msg.target.dispatchmessage回調到handler中去。
looper把消息回調到handler的dispatchmessage中進行消息處理:
若該消息有callback,即通過post(runnable)的方式投遞消息,因為在投遞<code>runnable</code>時,把<code>runnable</code>對象指派給了message的<code>callback</code>。
若handler的mcallback不為空,則交由通過<code>callback</code>建立handler方式去處理。
否則,由最常見建立handler對象的方式,在重寫handlermessage中處理。
以一個時序圖來總結handler的消息機制,包含上述如何關聯looper和messagequeue的過程。
handler-looper-messagequeue時序圖