Handler:誰發(fā)送愧驱,誰處理狠鸳,主要工作就是消息的發(fā)送和接收過程夺饲。消息的發(fā)送可以通過post的一系列方法以及send的一系列方法來實現(xiàn)装盯,post的方式最終是通過send的方法來實現(xiàn)的废睦。
Handler發(fā)送一條消息的過程
public final boolean sendMessage(Message msg){
return sendMessageDelayed(msg,0);
}
public final boolean sendMessageDelayed(Message msg,long delayMillis){
if(delayMillis<0){
delayedMillis=0;
}
return sendMessageAtTime(msg,SystemColock.uptimeMillis()+delayMillis);
}
public boolean sendMessageAtTime(Message msg,long uptimeMillis){
MessageQueue queue=mQueue;
if(queue==null){
RuntimeExection e=new RuntimeException(this+"sendMessageAtTime() called with no mQuene")
Log.w("looper",e.getMessage(),e);
return false;
}
//向隊列中插入一條消息
return enqueueMessage(queue,msg,uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue,Message msg,long uptimeMillis){
msg.target=this;
if(mAsynchronous){
msg.setAsychronous(true);
}
return queue.enqueueMessage(msg,uptimeMillis);
}
Handler發(fā)送消息的過程是向消息隊列中插入一條消息伺绽,MessageQueue的next方法就會返回這條消息給Looper,Looper收到這條消息之后就開始處理了嗜湃,最終消息由looper交由Handler處理奈应,即Handler的dispatchmessage方法會被調(diào)用,這是Handler就進入處理消息的階段购披。
public void dispatchMessage(Message msg){
//檢查message的callback是否為null
if(msg.calllback!=null){
handleCallback(msg);
}
else{
if(mCallback!=null){
if(mCallback.handleMessage(mssg)){
return;
}
}
handleMessage(msg);
}
}
Handlet處理消息的過程
首先杖挣,檢查Message的callback是否為null,不為空就通過handleCallback來處理消息。message的callback是一個Runnbale對象刚陡,實際上就是Handler的post方法所傳遞的Runnable參數(shù)惩妇。
private static void handleCallback(Message message){
message.callback.run();
}
其次,檢查mCallback是否為空筐乳,不為null及調(diào)用mCallback的handleMessage方法來處理消息
public interface Callback{
public boolean handleMessage(Message msg);
}

從這個圖中我們很清楚可以看到調(diào)用sendEmptyMessage后歌殃,會把Message對象放入一個MessageQueue隊列,該隊列屬于某個Looper對象蝙云,每個Looper對象通過ThreadLocal.set(new Looper())跟一個Thread綁定了氓皱,Looper對象所屬的線程在Looper.Loop方法中循環(huán)執(zhí)行從MessageQueue隊列讀取Message對象,并把Message對象交由Handler處理勃刨,調(diào)用Handler的dispatchMessage方法波材。
現(xiàn)在我們再來看一下使用Handler的基本實現(xiàn)代碼:
// 主線程中新建一個handler
Handler h= new Handler() {
public void handleMessage(android.os.Message msg) {
}
};
Android的消息機制主要是Handler的運行機制,Handler的運行需要底層MessageQueue和looper的支撐身隐。
MessageQueue:消息隊列廷区,內(nèi)部存儲了 一組消息,以隊列的形式提供插入和刪除的工作抡医。
Looper:消息循環(huán)躲因,由于MessageQueue只是一個消息的存儲單元 ,他不能去處理消息忌傻,Looper就填補了這個功能大脉,Looper會以無限循環(huán)的形式去找是否有這個消息,如果有消息的話就處理消息水孩,否則就一直等待镰矿。線程是默認沒有Looper的,如果需要使用Handler及必須為線程創(chuàng)建Looper俘种。
在一個Android程序中開始運行的時候秤标,會單獨開啟一個進程绝淡。默認的情況下所有這個程序中(四大組件)Activity,Service,Content Provider ,Broadcase Receiver 都會跑在這個進程中苍姜。一個Android程序默認情況下也只有一個進程牢酵,但一個進程卻可以有多個線程(Thread)。在這么多Thread當中衙猪,有一個Thread,我們稱之為UI Thread.UI Thread在Android程序運行的時候就被創(chuàng)建馍乙,是一個Process當中的主線程Main Thread,主要是負責控制UI界面的顯示垫释、更新和控件交互丝格。在Android程序創(chuàng)建之初,一個Process呈現(xiàn)的是單線程模型棵譬,所有的任務都在一個線程中運行显蝌。因此,我們認為订咸,UI Thread所執(zhí)行的每一個函數(shù)曼尊,所花費的時間都應該是越短越好。而其他比較費時的工作(訪問網(wǎng)絡算谈,下載數(shù)據(jù)涩禀,查詢數(shù)據(jù)庫等),都應該交由子線程去執(zhí)行然眼,以免阻塞主線程艾船,導致ANR。那么問題來了高每,UI 主線程和子線程是怎么通信的呢屿岂。這就要提到我們這里要講的Handler機制。
Handler機制被引入的目的就是為了實現(xiàn)線程間通信鲸匿。Handler一共干了兩件事:在子線程中發(fā)出massage,在主線程獲取爷怀,處理message。聽起來好像很容易带欢,如果面試中讓你闡述下Handler機制运授,我們這么回答顯然不是面試官想要的答案。我們忽略了一個問題:子線程何時發(fā)送message,主線程何時獲取處理message乔煞。

在這張圖我們可以看到首先在ActivityThread創(chuàng)建UI線程吁朦,然后會看到有一個Looper.prepareMainLooper(),此時會創(chuàng)建Looper對象和MessageQueue對象,當在UI線程new Handler()時渡贾,此時逗宜,Handler與Looper,MessageQueue建立關(guān)聯(lián),這個纺讲,當子線程handler.sendMessage(message)時擂仍,Looper.loop()會在messageQueue循環(huán)讀取對象Message msg=queue.next(),然后分發(fā)消息給Handler,有他來處理消息msg.target.dispatchMessage(msg),最后調(diào)用handleMessage(msg)處理消息,更細UI線程熬甚。

助理小怡(Looper)
助理小怡的工作內(nèi)容主要有兩件事情逢渔,第一件事情是做好準備工作(Looper.prepare()),即到某寶上包郵購買了一個消息盒子(MessageQueue)乡括,用來收集攻城獅們(Thread)的各種訴求(Message)复局。第二件事情是開啟無限循環(huán)的工作模式(Looper.loop()),她無比勤勞的等待著攻城獅們的各種召喚粟判,收集他們的訴求,并傳達給技術(shù)總監(jiān)峦剔。
技術(shù)總監(jiān)(Handler)
助理Looper在loop()中通過msg.target.dispatchMessage(msg)將消息分發(fā)給技術(shù)總監(jiān)Handler档礁,那么Handler將如何對這些Message進行處理.