標籤:
Android中的訊息處理機制由四個部分組成:Message、Handler、MessageQueue和Looper,並且MessageQueue封裝在Looper中,我們一般不直接與MQ打交道。
一、Looper
Looper的字面意思是“迴圈者”,它被設計用來使一個普通線程變成Looper線程。所謂Looper線程就是迴圈工作的線程。在程式開發中(尤其是GUI開發中),我們經常會需要一個線程不斷迴圈,一旦有新任務則執行,執行完繼續等待下一個任務,這就是Looper線程。
一個線程中只有一個Looper對象,一個Looper對象只有一個MessageQueue,而一個線程中可以有多個hander,可以根據需要為hander設定不同的Looper進行處理。
那麼如何將一個線程變為Looper線程呢?其實很簡單,只需要在該線程中加入以下兩行代碼:
public class LooperThread extends Thread { @Override public void run() { // 將當前線程初始化為Looper線程 Looper.prepare(); // ...其他處理,如執行個體化handler // 開始迴圈處理訊息佇列 Looper.loop(); }}
調用Looper.prepare()方法是為了為當前線程的ThreadLocal(關於ThreadLocal的解釋詳見http://blog.csdn.net/qjyong/article/details/2158097)設值(就我的理解就是建立一個新的Looper給當前線程使用,當一個線程有了Looper對象後該線程就可變為Looper線程了)。然後再調用Looper.loop()方法就讓該Looper線程開始工作了,Looper會不斷的從自己的MessageQueue中取出隊頭的訊息進行處理。
除了prepare()和loop()Looper類還有其它的一些方法:
Looper.myLooper() 得到當前線程looper對象
getThread() 得到looper對象所屬線程
quit() 方法結束looper迴圈
二、Handler
handler扮演了往MQ上添加訊息和處理訊息的角色(只處理由自己發出的訊息),即通知MQ它要執行一個任務(sendMessage),並在loop到自己的時候執行該任務(handleMessage),整個過程是非同步。handler建立時會關聯一個looper,預設的構造方法將關聯當前線程的looper,不過這也是可以set的。
有了handler之後,我們就可以使用 post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long), sendEmptyMessage(int),
sendMessage(Message), sendMessageAtTime(Message, long)和 sendMessageDelayed(Message, long)這些方法向MQ上發送訊息了;使用dispatchMessage(
Message msg)與方法handleMessage(Message msg)。光看這些API你可能會覺得handler能發兩種訊息,一種是Runnable對象,一種是message對象,這是直觀的理解,但其實post發出的Runnable對象最後都被封裝成message對象了,一般我們使用Handler的的sendMessage()方法來發送訊息到訊息佇列中,使用handleMessage()方法來處理訊息佇列中當前handler所發送的訊息。
Handler的作用:
1.handler可以在任意線程發送訊息,這些訊息會被添加到該handler關聯的MQ上。
2.handler是在它關聯的looper線程中處理訊息的。
這就是android中為什麼不能在其他非主線程中更新UI的問題。android的主線程也是一個looper線程,我們在其中建立的handler預設將關聯主線程MQ。因此,利用handler的一個solution就是在activity中建立handler並將其引用傳遞給worker thread,worker thread執行完任務後使用handler發送訊息通知activity更新UI(我的理解就是主線程開啟時會自動建立有對應的Handler、Looper和MessageQueue,其所做的操作就是當對介面進行修改時會發送一條訊息到訊息佇列中由Handler取出去進行處理,單當開啟子線程後子線程中不會自動建立Handler、Looper和MessageQueue,這樣當進行介面勻速修改時是沒有訊息去通知當前主線程的handler去處理這一動作的,所以要我們自己在子線程中建立一個使用主線程的Looper和MessageQueue的handler發送訊息),如:
三、Message
在整個訊息處理機制中,message又叫task,封裝了任務攜帶的資訊和處理該任務的handler。
1.儘管Message有public的預設構造方法,但是你應該通過Message.obtain()來從訊息池中獲得空訊息對象,以節省資源。
2.如果你的message只需要攜帶簡單的int資訊,請優先使用Message.arg1和Message.arg2來傳遞資訊,這比用Bundle更省記憶體
3.擅用message.what來標識資訊,以便用不同方式處理message。
android基礎(六)android的訊息處理機制