說到 Android 消息機制,就不得不談到 Handler 機制,接下來本文以 android-29 的源碼分析 Handler 機制的原理。
首先 Handler 是在 android.os 包下,與它在同一個包下的 Looper,Message,MessageQueue 等就是本文的重點。
// 舉個例子
這是 handler 在子線程使用的典型執行個體,下面按步驟分析:
1. Looper.prepare()
static
調用後建立了 MessageQueue 和 Looper,并把 looper 的執行個體放入 ThreadLocal 中儲存
2. 建立 handler
Handler提供了兩種使用方式
第一種方式是直接執行個體化,調用handler的構造函數
//Handler.java#構造函數一
構造函數裡有三個參數,分别是
looper:建立了 MessageQueue,在某個線程中周遊對應的消息隊列,相當于發動機的角色。
callback:定義了 handleMessage() 方法,對接收到的消息進行處理,相當于快遞分揀員的角色。
async:設定消息是否異步,預設是同步的,如果是異步将不受同步障礙的限制。
第二種方式是繼承 handler,重寫 handleMessage() 方法。
建立 handler 後,handler 就持有了 looper 和 messageQueue 的對象引用, 通過調用 sendMessage() 方法往 messageQueue 中發送消息,其實最終調用的是 MessageQueue的enqueueMessage() 方法
boolean
TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t))); 這行代碼會不斷地調用write()方法,直到管道中的資料全部讀完
3.Looper.loop()
//Looper.java#裁剪代碼
這裡重點分析 Message msg = queue.next();
Message
mPtr的指派是nativeInit(),網上暫時沒找到Android Q的線上檢視,暫時以Android P來分析native層的邏輯。 native層建立NativeMessageQueue對象後将對象id傳回給java層,其中NativeMessageQueue建立時建立了Looper對象, 與java層Looper對象在建立時建立了MessageQueue對象恰恰相反
static
nativePollOnce()調用到native層,将mPtr根據id轉為NativeMessageQueue對象
static
至此流程分析結束,下面附上總結圖
Handler通過sendMessage()發送Message到MessageQueue隊列;
Looper通過loop(),不斷提取出達到觸發條件的Message,并将Message交給target來處理;
經過dispatchMessage()後,交回給Handler的handleMessage()來進行相應地處理。
将Message加入MessageQueue時,處往管道寫入字元,可以會喚醒loop線程;如果MessageQueue中沒有Message,并處于Idle狀态,則會執行IdelHandler接口中的方法,往往用于做一些清理性地工作。
Tips:
1.為什麼在主線程中使用handler不用調用Looper.prepareMainLooper()和Looper.loop()? 這是因為 ActivityThread 在初始化時已經調用過了,具體見如下源碼。
//ActivityThread.java#
2.主線程中的Looper.loop()一直無限循環為什麼不會造成ANR? 首先要明白ANR的定義,activity逾時5s,service逾時10s,broadcast逾時20s,才會導緻Application Not Response。
參考資料:
http://androidxref.com/http://gityuan.com/2015/12/26/handler-message-framework/http://gityuan.com/2015/12/27/handler-message-native/