一、從構造函數開始
可以看到,Handler的構造函數里,關聯了Looper(通過Looper.myLooper()方式取得)、Queue(MessageQueue,從Looper中取得)、Callback()、async.
接下來,看一下 Looper.myLooper():
myLooper()取得的Looper是存儲在ThreadLocal中的。通過looper.prepare()初始化并存儲:
通過方法,可以看到,prepare()函數只能被調用一次,不然會throw Exception。這樣可以保證,一個ThreadLocal中只存在一個Looper。
再看Looper的構造函數:
在looper的構造方法里,主要做了兩件事:
1、創建一個looper管理的消息隊messageQueue;
2、獲得當前的線程;
到這里,Handler的構造函數,基本流程跑完。總結一下,new 一個handler的時候,會得到一個綁定在ThreadLocal中的Looper實例、一個與Looper綁定的MessageQueue實例,這三個實例對象互相綁定,從而進行信息交流。
二、信息發送流程。
handler通過sendMessage()、sendMessageDelayed()、sendMessageAtTime()等方法發送信息,最終這些方法都會走入同一個方法:enqueueMessage()
在enqueueMessage()方法中,先是將本handler對象賦值msg.target.之后執行了messageQueue的消息隊列插入消息操作MessageQueue.enqueueMessage():
此函數執行的是單鏈表的插入操作,從此也可以看出。MessageQueue實際上是由單鏈表實現的。
三、消息處理流程。
將Message插入MessageQueue之后,我們知道。與MessageQueue綁定的Looper會調用 loop()方法一直循環遍歷MessageQueue:
清晰明了,獲取當前looper和與其對應的MessageQueue。通過一個for(;;)死循環,從MessageQueue中遍歷獲取Message。這邊注意,messageQueue.next()方法中如果沒有Message,會在next()方法中block住,直到有Message被enQueue入MessageQueue隊列中,next()方法繼續執行,loop()也可以瞬間得到Message。而只有在looper調用quit()或quitSafely()方法,messageQueue的next()方法才會返回null(此時MessageQueue同樣調用了quit()方法),此時loop的無限循環也將結束。
looper.quit()和looper.quitSafely()的區別是:quit()直接退出Looper,quitSafely()只是設置一個退出標志,等消息隊列中的消息處理完畢,就會退出Looper,這時候Handler的send方法返回false。如果在子線程中手動創建了Looper,要記得退出Looper,不然這個線程會一直處于等待轉態,如果退出了,這個線程也會被終止。
接下來,我們來看一下 MessageQueue的next()方法:
就像我們之前說的那樣,如果單向鏈表中有Message,便取出這個Message return出去,如果鏈表中已經沒有Message,便通過Binder.flushPendingCommands() ?block當前操作。
回到Looper.loop()中,當looper從MessageQueue中得到Message之后,便會調用msg.target.dispatchMessage(msg)去處理Message。之前我們提到過,在Handler發送消息的enqueueMessage()方法中,已經將當前Handler賦值給了msg.target.此時,便是將發送message的handler變量取出,調用其dispatchMessage(msg)方法處理Message。
Handler的消息處理過程如下:
首先先檢查Message的callback是否為空,不為空就通過handleCallback來處理,Message的callback是一個Runnable對象,實際上就是Handler的post方法所傳遞的Runnable參數
其次檢查mCallback是否為null,不為null就調用mCallback的handleMessage方法來處理,Callback是個接口,定義如下:
public interface Callback {
?? ?public boolean handleMessage(Message msg); ? ?
}
通過Callback可以采用如下方法創建Handler handler = new Handler(callable)。在日常開發中,創建Handler最常見的方式是派生一個Handler的子類并且重寫它的handleMessage方法,另外一種是傳入一個Callback,并實現callback的handleMessage方法。
最后調用Handler的handleMessage方法來處理消息。
處理過程的流程圖:
四、Handler使用注意事項
1、創建massage對象時,推薦使用obtain()方法獲取,因為Message內部會維護一個Message池用于Message的復用,這樣就可以避免 重新new message而沖內心分配內存,減少new 對象產生的資源的消耗。
2、handler 的handleMessage方法內部如果有調用外部activity或者fragment的對象,一定要用弱飲用,handler最好定義成static的,這樣可以避免內存泄漏;為什么呢?因為一但handler發送了消息。而handler內部有對外部變量的引用,此時handler已經進入了looper的messageQueue里面。此時activity或者fragment退出了可是區域,但是handler內部持有其引用且為強引用時,其就不會立即銷毀,產生延遲銷毀的情況。