Android消息機制-Handler原理(三) -开发者知识库

Android消息機制-Handler原理(三) -开发者知识库,第1张

一 .Handler的執行過程

 1.定義Handler對象,重寫handleMessage方法

 2.handler 對象調用sendMessage 發送message,sendMessage 最終調用  sendMessageAtTime
  3.sendMessageAtTime方法又調用了 enqueueMessage 使message 加入到 消息隊列 MessageQueue,並且執行了msg.target = this 把handler對象賦值給message對象的target屬性
  4.線程中的Looper執行loop()方法,不斷從消息隊列當中讀取消息。
  5.loop()取到消息后,執行 msg.target.dispatchMessage(msg) ,也就是執行Handler對象當中的dispatchMessage方法
  6.最終dispatchMessage 方法,可以執行第一步handler對象重寫的handleMessage繼而完成了整個消息傳遞

補充 7.如果,第二步中Handler 使用post方法發送一個runable對象而非send方法,runable傳遞給了message的callback,最終在dispatchMessage 中,判斷callback!=null從而執行了runable對象

二 .相關類

A.Handler:作用是發送消息,執行消息

Handler的相關方法已經介紹過了,這里 ,最終發送消息都指向了sendMessageAtTime(除了sendMessageAtFrontOfQueue
//sendMessageAtTime源碼
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
最終執行消息都指向了dispatchMessage

B. Message:消息,target屬性攜帶handler對象,callback屬性可攜帶Runable對象

C.MessageQueue:消息隊列,一個線程只有一個消息隊列

類似現實中買票,每個人都是一個messge,如果不排隊窗口售票員處理不過來,票也容易賣重復了。排成一隊,一個一個處理。 sendMessageAtTime中調用了MessageQueue 的 enqueueMessage 方法使消息加入消息隊列。
Looper調用MessageQueue的next方法從消息隊列中取消息。

D.Looper:循環從MessageQueue里面取消息,並dispatch調度消息。每個線程一個Looper實例

1. Looper才是使消息隊列循環起來的類,在UI主線程中,Actitivy創建的時候,已經執行了Looper.loop() 。在Activity源碼中定義了變量ActivityThread 類型的變量  mMainThread,他就代表了主線程。ActivityThread 中定義了Looper,並最終執行了Looper.loop()。所以在主線程中,可以直接發送消息,並且取消息。
2.但是在Thread中,並沒有定義和調用Looper.loop(),這樣你發消息取不出來,執行不了,所以,在子線程要想執行Handler 這一套機制,必須在Thread里調用Looper.loop()是消息循環起來
Handler機制的作用什么,是讓線程A發消息,告訴B線程執行消息。 這里既可以子線程發送消息,讓主線程執行消息; 又可以主線程發消息讓子線程執行消息。 Handler  發消息的線程消息執行的線程是兩個概念。這里,子線程里給主線程send消息,會使消息在主線程執行。 主線程給子線程send消息,會使消息在子線程執行。
進一步,主線程在創建的時候,就已經執行了Looper.loop() 監聽消息隊列。 所以子線程發消息給主線程,可以隨時就執行了 但是,主線程發消息給子線程,子線程默認又沒有監聽消息隊列,發了消息沒人收。所以才需要先執行 Looper.prepare()  使線程綁定Looper對象,然后執行Looper.loop() 使消息隊列動起來,循環監聽消息隊列。
實際上,主線程發消息讓子線程執行消息是不常見的,主要是為了解釋清楚 Looper.prepare() 是和線程綁定,Looper.loop() 可以使線程循環監聽消息隊列。Looper才不管你是不是主線程,它只是讓綁定它的線程具有循環監聽消息隊列的功能

最佳答案:

本文经用户投稿或网站收集转载,如有侵权请联系本站。

发表评论

0条回复