Message,MessageQueue,Looper,Handler詳解

jackie_gnu發表於2011-09-21

from:http://hi.baidu.com/%CE%DE%D0%C4%B1%B1%BE%A9/blog/item/82897fae220a7ad67dd92ad7.html 

一、幾個關鍵概念

1、MessageQueue:是一種資料結構,見名知義,就是一個訊息佇列,存放訊息的地方。每一個執行緒最多隻可以擁有一個MessageQueue資料結構。
建立一個執行緒的時候,並不會自動建立其MessageQueue。通常使用一個Looper物件對該執行緒的MessageQueue進行管理。主執行緒建立時,會建立一個預設的Looper物件,而Looper物件的建立,將自動建立一個Message Queue。其他非主執行緒,不會自動建立Looper,要需要的時候,通過呼叫prepare函式來實現。

2、Message:訊息物件,Message Queue中的存放的物件。一個Message Queue中包含多個Message。
Message例項物件的取得,通常使用Message類裡的靜態方法obtain(),該方法有多個過載版本可供選擇;它的建立並不一定是直接建立一個新的例項,而是先從Message Pool(訊息池)中看有沒有可用的Message例項,存在則直接取出返回這個例項。如果Message Pool中沒有可用的Message例項,則才用給定的引數建立一個Message物件。呼叫removeMessages()時,將Message從Message Queue中刪除,同時放入到Message Pool中。除了上面這種方式,也可以通過Handler物件的obtainMessage()獲取一個Message例項。

3、Looper:
是MessageQueue的管理者。每一個MessageQueue都不能脫離Looper而存在,Looper物件的建立是通過prepare函式來實現的。同時每一個Looper物件和一個執行緒關聯。通過呼叫Looper.myLooper()可以獲得當前執行緒的Looper物件建立一個Looper物件時,會同時建立一個MessageQueue物件。除了主執行緒有預設的Looper,其他執行緒預設是沒有MessageQueue物件的,所以,不能接受Message。如需要接受,自己定義一個Looper物件(通過prepare函式),這樣該執行緒就有了自己的Looper物件和MessageQueue資料結構了。
Looper從MessageQueue中取出Message然後,交由Handler的handleMessage進行處理。處理完成後,呼叫Message.recycle()將其放入Message Pool中。

4、Handler:
訊息的處理者,handler負責將需要傳遞的資訊封裝成Message,通過呼叫handler物件的obtainMessage()來實現;
將訊息傳遞給Looper,這是通過handler物件的sendMessage()來實現的。繼而由Looper將Message放入MessageQueue中。
當Looper物件看到MessageQueue中含有Message,就將其廣播出去。該handler物件收到該訊息後,呼叫相應的handler物件的handleMessage()方法對其進行處理。

 

 

每個執行緒都有一個looper,
looper擁有一個message queue
looper是一個死迴圈,不停處理message queue中的訊息。

handler是方便多執行緒處理或非同步處理而建立的資料結構,
它擁有兩個成員,一個指向handler被建立的執行緒的looper,一個是該執行緒的訊息佇列。

所以,呼叫handler的post方法,實際上是把訊息放到了該執行緒的訊息佇列(注意,不是當前執行緒,如果你在主執行緒中建立的handler,在子執行緒中呼叫handler的post方法,實際上是把訊息傳送到主執行緒的訊息佇列);每個訊息有一個target成員,handler傳送過去的訊息會把該訊息的target設定稱為自己。

looper收到訊息後會處理,並且把訊息傳送給target,也就是說訊息轉了一圈又回到了handler,handler可以做出理。這個過程看似繞道,實際上很有必要,呼叫handler post是在子執行緒中,而handler的處理方法是在主執行緒中被呼叫的,這個過程伴隨一次執行緒排程的。

下圖描述了looper, messsage queue, handler, message之間的關係


 

相關文章