handler底層是如何將消息從子線程發送到主線程

這個問題的實質是handler機制+引用的傳遞.
理解handler機制有很多方法,我推薦的方法是從四個關鍵類Handler、Message、MessageQueue、Looper的方法入手來弄清消息傳遞這一整條線的邏輯:
這條線的走向是:(相關對外提供的方法可以用eclipse或者source insight來查看.)
1產生消息對象
2-->消息相關屬性(what,obj,target,callback等)的附加
3-->消息加入到消息隊列
4-->Looper對消息隊列的循環取出
5-->分發(也就是執行消息內用戶定義的處理邏輯)
6-->回收消息對象

從子線程發送到主線程的消息分兩種,一種是普通的handler.sendMessage(msg)或定義延時send,另一種是handler.post(Runnable r)或定時或延時post.不管是哪一種,都用到了handler,那麼這個handler就會賦值給msg.target.
常見的情況下,handler在主線程中new出來,然後在子線程中拿到它的引用,發送了消息,系統把消息加入到消息隊列中,然後就會有一個Looper來從消息隊列中取消息.

這個流程中要注意幾個對應關係:
一個線程中最多隻能有一個Looper,也可以沒有.主線程中初始化時已建立Looper.子線程默認沒有,如果使用,需要手動創建.
一個Looper對應一個消息隊列.也就是說,有幾個Looper,就有幾個消息隊列,

那麼一個Message發送時,怎麼知道它要加入到哪個消息隊列中去?
一個handler持有一個消息隊列的引用和它構造時所屬線程的Looper的引用.
也就是說,一個handler必定有它對應的消息隊列和Looper,
一個線程至多能有一個Looper,也就至多能有一個消息隊列.
一個線程中可以有多個handler.

在主線程中new了handler對象後,這個handler對象自動和主線程自動生成的Looper以及消息隊列關聯上了.
子線程中拿到主線程中handler的引用,發送消息後,消息對象就會發送到target屬性對應的那個handler對應的消息隊列中去,由對應的Looper來取出處理.
而消息發送到主線程handler,那麼也就是發送到主線程的消息隊列,用主線程中的Looper輪詢.

Looper的loop方法在它關聯的線程中執行(比如主線程),但這是一個阻塞式方法,由消息觸發後調用循環內部後面部分的handler.dispatchMessage(),實質是調用handler.handleMessage()或runnable.run()執行自定義的邏輯.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章