從開發(fā)角度來說,Handler是Android消息機制的上層接口,這使得開發(fā)過程中只需要和Handler交互即可。
1.1、Android的消息機制概述
簡單來講,Handler的運行需要底層的MessageQueue和Looper的支撐。MessageQueue是消息隊列,它的內(nèi)部存儲了一組消息,以隊列的的形式對外提供插入和刪除的工作,它的內(nèi)部是采用單鏈表的數(shù)據(jù)結(jié)構(gòu)來存儲消息列表。Looper可以理解為消息循環(huán)。Looper會以無限循環(huán)的形式在MessageQueue中查找是否有新消息,如果有就處理消息,否則一直等待著。Looper中還有一個特殊的概念,那就是ThreadLocal,ThreadLocal并不是線程,它的作用是可以在每個線程中存儲數(shù)據(jù)。
Handler創(chuàng)建的時候會采用當(dāng)前線程的Looper來構(gòu)造消息循環(huán)系統(tǒng),ThreadLocal可以再不同的線程中互不干擾地存儲并提供數(shù)據(jù),通過ThreadLocal可以輕松的獲取每個線程的Looper。
注意,線程默認(rèn)是沒有Looper的,如果需要使用Hnadler就必須為線程創(chuàng)建Looper。我們經(jīng)常提到的主線程也叫UI線程,他就是ActivityThread,ActivityThread被創(chuàng)建時就會初始化Looper,這也是主線程中默認(rèn)可以使用Handler的原因。
Android無法在子線程中更新UI,因為Android的UI控件不是線程安全的。
注意,Looper是運行在創(chuàng)建Handler所在的線程中的,這樣一來Handler中的業(yè)務(wù)邏輯就會被切換到創(chuàng)建Handler所在的線程中去執(zhí)行了。
1.2、Android的消息機制分析
1.2.1、ThreadLocal的工作原理
ThreadLocal是一個線程內(nèi)部的數(shù)據(jù)存儲類,通過它可以在指定的線程中存儲數(shù)據(jù)。只有在指定的線程中可以獲取到數(shù)據(jù)。
不同的線程創(chuàng)建了不同的Values,Values下有不同的數(shù)組table,所以不同的線程存儲的數(shù)據(jù)不同。
1.2.2、MessageQueue的工作原理
MessageQueue包含兩個操作:插入和讀取。讀取操作本身伴隨著刪除操作,插入和讀取對應(yīng)的方法分別是enqueueMessage(插入一條消息到消息隊列)和next(取出一條消息并將其從消息隊列中移除)。
1.2.3、Looper的工作原理
private Looper(boolean quitAllowed){
????????? mQueue = newMessageQueue(quitAllowed) ;
????????? mThread = Thread.currentThread() ;
}
從構(gòu)造方法可以看出,Looper會創(chuàng)建一個MessageQueue,然后將當(dāng)前線程對象保存。
Handler的工作需要Looper,沒有Looper的線程就會報錯。創(chuàng)建Looper:
Looper.prepare()即可為當(dāng)前線程創(chuàng)建一個Looper,接著通過Looper.loop()來開啟消息循環(huán)。
Looper提供了quit(直接退出)和quitSafely(消息隊列里的消息執(zhí)行完畢才退出)來退出一個Looper。
子線程中如手動創(chuàng)建了Looper,所有事情處理完后應(yīng)該調(diào)用quit,否則子線程一直等待狀態(tài)。
當(dāng)Looper方法是一個死循環(huán),唯一跳出循環(huán)的方式是MessageQueue的next方法反回了nul。當(dāng)Looper的quit方法調(diào)用時,Looper就會調(diào)用MessageQueue的quit或者quitSafely方法來通知消息隊列退出,當(dāng)消息隊列標(biāo)記為退出狀態(tài)是,它的next方法就會返回null。
所以說Looper必須退出,否則loop就會一直循環(huán)下去。當(dāng)loop方法去調(diào)用MessageQueue的next方法來獲取新消息,而next是一個阻塞操作,當(dāng)沒有消息時,next方法會一直阻塞,導(dǎo)致loop方法一直阻塞在那里。有消息looper處理:msg.target.dispatchMessage(msg) ;msg.target是發(fā)送這條消息的Handler對象。
1.2.4、Handler的工作原理
Handler的工作包括消息的發(fā)送和接收過程。發(fā)送可用post系列方法和send系列方法。(post最終通過send)。
Handler發(fā)送消息的過程僅僅是向消息隊列中插入了一條消息,MessageQueue的next方法就會返回這條消息給Looper,Looper收到消息后就開始處理消息,最終消息由Looper交給Handler處理,即handler的dispatchMesage方法被調(diào)用。
Handler處理消息的三個方式對應(yīng)dispatchMesage方法的三個處理情況 :
1)handler.post(Runnable r)
2) handler = new Handler(callback)
3) 派生子類,重寫handleMessage方法。
Handler還有一個特殊的構(gòu)造方法,那就是通過特定的Looper來構(gòu)造Handler
public?? Handler (Looper looper){
?????????? this(looper,null,false) ;
}
可以實現(xiàn)一些特殊的功能。