Android開發中老是免不了處理一些耗時的操做,如網絡請求、IO文件讀寫等等,都須要用子線程來處理,耗時操做每每也伴隨着更新UI的顯示。此時就涉及到UI線程與子線程之間的通訊問題。爲此Android系統引入了Handler異步消息處理的機制。java
Android中想要在子線程中更新UI,一般有三種辦法:網絡
Handler的post方法,應該都很清楚,內部的Runnable的run方法已是在UI線程執行了。View的post方法、Activity的runOnUiThread()方法怎麼也能夠在UI線程呢,來看看其內部實現:架構
// View.java
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Postpone the runnable until we know on which thread it needs to run.
// Assume that the runnable will be successfully placed after attach.
getRunQueue().post(action);
return true;
}
// Activity.java
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
複製代碼
很顯然從源碼能夠看出最終都是交給主線程Handler的post方法來處理。那麼爲何主線程聲明實例化的Handler的post方法在子線程調用就能夠用來更新UI呢?這個問題暫時先放這裏。接下來進一步分析Handler。異步
在Handler的消息處理架構中,和Message、MessageQueue、Looper這三個類是緊密相連的。 Message:消息數據承載類,能夠是事件任務消息,也能夠是其它的實體數據消息。 MessageQueue:消息隊列。用於將消息入隊和出隊,以及消息從隊列刪除釋放的管理。 Looper:消息循環處理器。用於維持一個死循環不斷的從MessageQueue中取出消息,並將消息分發給設置的目標對象處理(target即Handler)。 Handler:它是整個機制的輔助類。也是提供給客戶端使用對外暴露Api。用於輔助把消息加入隊列、刪除釋放消息事件和消息的回調處理。oop
Handler中咱們最經常使用的有post()、postDelay()、sendMessage()等方法,直接或者間接的在內部構建一個Message消息對象而後經過MQ(MessageQueue)的enqueueMessage來處理消息入隊的工做。App啓動的時候在ActivityThread類的main方法裏就先經過prepareMainLooper方法預加載了一個Looper對象,而後經過loop方法開啓了消息循環器。post
// ActivityThread.java
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
...
Looper.loop();
...
}
複製代碼
以上的Looper對象是主線程的,所以構造的MQ消息隊列也是主線程的,loop()方法中不斷循環取出隊列中的消息,經過handler的dispatchMessage方法分發消息。固然從一個事件消息的發送入隊到出隊處理回調不必定是實時的,MQ的enqueueMessage和next方法能夠看出它是一個單向鏈表隊列,入隊的時候根據消息發送的時間when按升序排序,當when爲0時插入到隊列頭部。spa