前言
什么叫又熟悉又陌生纵刘,這些概念就是了。對(duì)于這些概念相信沒有人沒見過(guò)犬第,但是又沒有幾個(gè)人真正熟悉锦积,所以就一直朦朦朧朧恍恍惚惚凄凄慘慘戚戚。今天就來(lái)解決這些恩恩怨怨歉嗓,做個(gè)了斷丰介。
概念初探
上面是Runnable,Message,MessageQueue,Looper和Handler的關(guān)系簡(jiǎn)圖。其中:
- Runnable和Message可以被壓入某個(gè)MsaageQueue中鉴分,形成一個(gè)集合哮幢。注意:一般情況下某種類型的MsaageQueue只允許保存相同類型的Object。上圖中我們只是為了方便敘述才把它們混放在MessageQueue中志珍,實(shí)際源碼中需要先對(duì)Runnable進(jìn)行相應(yīng)轉(zhuǎn)換橙垢。
- Looper循環(huán)地去做某件事
它不斷地從MessageQueue中取出一個(gè)item,然后傳給Handler進(jìn)行處理伦糯。如此循環(huán)往復(fù)柜某,假如隊(duì)列為空,那么它會(huì)進(jìn)入休眠敛纲。 - Handle是真正“處理事情"的地方
它利用自身的處理機(jī)制喂击,對(duì)傳入的各種Object進(jìn)行相應(yīng)的處理并產(chǎn)生最終結(jié)果。
用一句話來(lái)概括它們载慈,就是:
Looper不斷獲取MessageQueue中的一個(gè)Message,然后由Handle來(lái)處理惭等。
1. Handler
不知道有沒有人注意過(guò),Handle和線程Thread是什么關(guān)系办铡。
public class Handler {...
final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;
}
從Handler的源碼中看不出與Thread有什么關(guān)系辞做,但其實(shí):
- 每個(gè)Thread只對(duì)應(yīng)一個(gè)Looper;
- 每個(gè) Looper只對(duì)應(yīng)一個(gè)MessageQueue;
- 每個(gè)MessageQueue中有N個(gè)Message;
- 每個(gè)Message中最多指定一個(gè)Handler來(lái)處理事件。
5.一個(gè)Thread可以對(duì)應(yīng)多個(gè)Handler寡具。
Handler是應(yīng)用開發(fā)人員經(jīng)常會(huì)使用到的一個(gè)類秤茅,它有兩個(gè)方面的作用。
- 處理Message童叠,這是它作為"處理者"的本職所在框喳。
- 將某個(gè)Message壓入MessageQueue中课幕。
#實(shí)現(xiàn)第一個(gè)功能的相應(yīng)函數(shù)
public void dispatchMessage (Message msg); //對(duì)Message進(jìn)行分發(fā)
public void handleMessage(Message msg); //對(duì)Message進(jìn)行處理
Looper從MessageQueue中取出一個(gè)Message后,首先使用調(diào)用dispatchMessage進(jìn)行消息派發(fā)五垮;后者則根據(jù)具體的策略來(lái)將Message分發(fā)給相應(yīng)的負(fù)責(zé)人乍惊。默認(rèn)情況下Handler的派發(fā)歷程是:
Message.callback(Runnable 對(duì)象)是否為空
在不為空的情況下,將優(yōu)先通過(guò)callback來(lái)處理
Handler.mCallback是否為空
在不為空的情況下放仗,調(diào)用mCallback.handleMessage
如果前兩個(gè)對(duì)象都不存在润绎,才調(diào)用Handler.handleMessage
由此可見,Handler的擴(kuò)展子類可以通過(guò)重載dispatchMessage或者HandleMessage來(lái)改變它的默認(rèn)行為诞挨。
Handler的第二個(gè)功能莉撇,容易引起開發(fā)人員的疑惑,因?yàn)檫@樣形成了Handler->MessageQueue->Message->Handler的循環(huán)惶傻。
#實(shí)現(xiàn)第二個(gè)功能的主要方法
1. post系列
final boolean post (Runnable r);
final boolean postAtTime(Runnable r, long uptimeMills);
2. Send系列
final boolean sendEmptyMessage(int what);
final boolean sendMessageAtFrontOfQueue(Message msg);
boolean sendMessageAtTime(Message msg, long uptimeMillis);
Post和Send的作用都是將某一個(gè)消息壓入MessageQueue中棍郎,區(qū)別在于后者處理的參數(shù)直接就是Message,而Post需要先將零散的信息轉(zhuǎn)換成Message,再調(diào)用Send系列函數(shù)來(lái)執(zhí)行下一步银室。
#post方法內(nèi)部
public final boolean post(Runable r){
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r){
Meaage m = Message.obtain();
/*
Android系統(tǒng)會(huì)維護(hù)一個(gè)全局的Message池涂佃。當(dāng)用戶需要時(shí)可以通過(guò)obtain函數(shù)獲得,避免產(chǎn)生不必要的資源浪費(fèi)粮揉。
*/
m.callback = r;/*將Runnable對(duì)象設(shè)置為Message的回調(diào)函數(shù)*/
return m;
}
有上述源代碼可以看出巡李,post實(shí)質(zhì)上是根據(jù)傳入的信息抚笔,從Mseeage池中獲得一個(gè)Message并將Runbale設(shè)置為Message的回調(diào)函數(shù)扶认。最后還是使用send函數(shù)將Message添加到MessageQueue。
2. MessageQueue
MessageQueue是一個(gè)消息隊(duì)列殊橙,因而它具有隊(duì)列的所有常規(guī)操作辐宾,包括:
- 新建隊(duì)列
由其構(gòu)造函數(shù)和本地方法nativeInit組成。其中nativeInit會(huì)在本地創(chuàng)建一個(gè)NativeMessageQueue對(duì)象膨蛮,然后直接賦值給MessageQueue中的成員變量叠纹。這一系列操作實(shí)際都是通過(guò)內(nèi)存指針進(jìn)行的。 - 元素入隊(duì)
final boolean enqueueMessage(Message msg, long when) - 元素出隊(duì)
final Message next() - 刪除元素
final void removeMessage(Handle h, int what, Object object)
final void removeMessage(Handler h, Runnable r, Object object) - 銷毀隊(duì)列
和創(chuàng)建過(guò)程一樣敞葛,還是通過(guò)本地的NativeDestory來(lái)銷毀一個(gè)MessageQueue誉察。
3. Looper
Looper有點(diǎn)類似于發(fā)動(dòng)機(jī),它的推動(dòng)使得整個(gè)Handler機(jī)制成為活源之水惹谐,不斷的處理新的消息持偏。Looper的使用有兩種情況,即在主線程以及在工作線程氨肌。
#工作線程的使用Looper的范例鸿秆。
class LooperThread extend Thread{
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg){
//處理消息的方法
}
};
looper.loop();//進(jìn)入主循環(huán)
}
}
這段代碼概括起來(lái)只有三個(gè)步驟:
- Looper的準(zhǔn)備工作(prepare)
- 創(chuàng)建處理消息的Handler
- Looper開始運(yùn)作(loop)
我們可以看到使用的步驟十分簡(jiǎn)單,但是仍有一些地方十分模糊怎囚,例如:looper是如何創(chuàng)建的,loop是如何與handler還有MeaasgeQueue進(jìn)行連接的卿叽。
首先我們發(fā)現(xiàn)在上述調(diào)用中使用了Looper.prepare()函數(shù),既然要用Looper類的函數(shù),那么LooperThread中肯定就得import android.os.Looper;觀察Looper類我們發(fā)現(xiàn)在Looper類里有一個(gè)很重要的成員
static final ThreadLocal<Looper> sThreadLoal = new ThreadLocal <Looper> ();
這是一個(gè)靜態(tài)變量考婴,這就意味著在引用Looper時(shí)贩虾,sThreadLocal時(shí)就已經(jīng)存在并成功構(gòu)建。ThreadLocal對(duì)象是一種特殊的全局變量沥阱,但是這種全局只局限與線程內(nèi)整胃,這就意味著每個(gè)線程的Looper都是獨(dú)立的。Looper為我們提供了很多靜態(tài)方法喳钟,可這畢竟是公共的方法屁使,其內(nèi)部還需要有針對(duì)每個(gè)Thread的特定存儲(chǔ)空間。因而sThreadLocal肯定會(huì)創(chuàng)建一個(gè)只針對(duì)當(dāng)前線程的Looper以及其他相關(guān)的對(duì)象奔则,而且這個(gè)操作很可能在prepare()蛮寂。
private static void prepare(boolean quitAllowed){
if(sThreadLocal.get() != null){
throw new RuntimeException("Only one Looper may be created per thread")
}//這個(gè)判斷保證一個(gè)線程中只有一個(gè)Looper實(shí)例。
sThreadLocal.set(new Looper(quitAllowed));
}
由上述代碼我們可以看出易茬,sThreadLocal存儲(chǔ)了一個(gè)Looper對(duì)象酬蹋。
接下來(lái)創(chuàng)建一個(gè)Handler對(duì)象,這個(gè)步驟看起來(lái)也是平淡無(wú)奇抽莱,就是使用Handler的構(gòu)造函數(shù)創(chuàng)建一個(gè)實(shí)例范抓。那么,Handler到底與Looper是如何連接起來(lái)的呢食铐?沒錯(cuò)就是構(gòu)造函數(shù)匕垫。
Handler有很多構(gòu)造函數(shù):
public Handler();
public Handler(Callback callback);
public Handler(Looper looper);
public Handler(Looper looper, Callback callback);
之所以會(huì)有那么多參數(shù),是因?yàn)镠andler中有很多內(nèi)部變量需要初始化
final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;
以第一個(gè)無(wú)參構(gòu)造函數(shù)為例:
public Handler(){
/*省略部分代碼*/
mLooper = Looper.myLooper();//還是通過(guò)sThreadLocal.get()來(lái)獲取當(dāng)前線程中的實(shí)例虐呻。
...
mQueue = mLooper.mQueue;//mQueue是Looper與Handler之間溝通的橋梁
mCallback = null;
}
這樣Handler和Looper象泵,MessageQueue就聯(lián)系起來(lái)了。后續(xù)Handler執(zhí)行Post/Send兩個(gè)操作時(shí)斟叼,會(huì)將消息投遞到mQueue也就是mLooper.mQueue中偶惠,一旦Looper處理到這一消息,它又會(huì)從中調(diào)出Handler進(jìn)行處理朗涩。
好了就剩下Looper.loop()了忽孽,這部分需要借助ActivityThread講解⌒淮玻看到這里一定有一點(diǎn)累了兄一,喝口小茶,歇息幾分鐘萤悴,下一篇再仔細(xì)說(shuō)明瘾腰。