要理解 Handler,就得先理解 Android 的 Message 機制.
這里以用戶滑動微信朋友圈為例,講解一下 Android 的 Message 機制是怎么運行的,Message 機制中的各個核心組件都做了什么
Message 產生
用戶滑動螢屏,產生了一系列 input 事件 (一個 Down 事件,若干個 Move 事件,一個 Up 事件),這些事件被系統包裝成了一系列 Message(一個 Down Message,若干個 Move Message,一個 Up Message)
Message 是用來傳遞資訊的,上述 Message 中就包含了這些 input 事件的資訊,比如 x 坐標,y 坐標,
MessageQueue 存放 Message
Message 產生后,有一個問題就是這些 Message 怎么發給應用?我要滑動朋友圈,那么這些個 Message 就得傳給微信,讓微信去處理,微信將這些事件給到朋友圈的 List 控制元件,讓 List 產生新內容,并且實作上下滑動,
首先想到的能不能直接把這些 Message 給到朋友圈的 List 控制元件(SystemServer 可以直接 Binder 發給 List 控制元件),可以是可以,但是麻煩;SystemServer 直接給朋友圈的 List 控制元件發 input message,那 SystemServer 得先知道有這么個控制元件,問題是應用有哪些控制元件,SystemServer 是不知道的,難道要遍歷所有的控制元件,每個控制元件都發一個重復的 Message?這顯然不是我們想要的,
SystemServer 不能直接發給控制元件,那么能不能直接發給應用,讓應用自己去處理呢?答案是肯定的,現在的 Android 也是這么做的, 你應用準備一個 MessageQueue(訊息佇列),我有 Message 就放到這個 MessageQueue 里面,你應用自己去處理,豈不美哉,這就是 MessageQueue 出現的原因
Looper 派發 Message
應用準備了一個 MessageQueue 之后,SystemServer 把之前包裝好的一系列 Input Message(一系列 Message(一個 Down Message,若干個 Move Message,一個 Up Message))放到了微信的 MessageQueue 里面,剩下的就讓微信自己去讀取 MessageQueue 里面的內容,自己更新 UI 去
問題是 MessageQueue 只是用來存放 Message 的,得有人來管理這個 MessageQueue,比如 MessageQueue 里面進了幾個 Message,這些 Message 該到發給誰去處理?
這里就引入了 Looper,Looper 來決定這個 Message 該發給誰去處理,Looper 會按照 Message 在 MessageQueue 里面的順序,一個一個取出 Message,根據 Message 自帶的資訊(我想被誰處理 - target),發給對應的人去處理
這個例子里面,這些 Message 的 target 就是微信的主執行緒的 handler
Handler 處理 Message
這時候,Handler 出場了,上面說 Looper 把 Message 發給對應的人去處理,這個人就是 Handler,Handler 就是用來處理 Message 的,作為 Message 機制的最后一環,Handler 讀取 Message 內容后,根據內容來做相關的處理,
這個例子里面,一系列 Input Message 最侄訓由微信的主執行緒 Handler 來處理,經過復雜的事件傳遞和事件分發流程,傳給對應的 List 控制元件,List 控制元件根據 Input Message 里面的內容,計算出自己下一幀的各個 Item 的位置,更新自己的 Item 和 Item 內的內容,從而產生 List 滑動效果,朋友圈滑動的流程就完成了
Message 機制總結
有了上面的 Message 機制的案例,理解下面這張圖就順理成章了,如上面幾個標題所示
- Message 承載內容
- MessageQueue 存放 Message
- Looper 派發 Message
- Handler 處理 Message

App 主執行緒
那么,App 主執行緒是怎么回事?下面是 App 行程創建后,ActivityThread.main 方法被呼叫的邏輯
frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
......
// 創建 Looper、Handler、MessageQueue
Looper.prepareMainLooper();
......
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
// 指定主執行緒的 handler 為 H
sMainThreadHandler = thread.getHandler();
}
......
// 開始準備接收訊息
Looper.loop();
}
}
// 準備主執行緒的 Looper
frameworks/base/core/java/android/os/Looper.java
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
// prepare 方法中會創建一個 Looper 物件
frameworks/base/core/java/android/os/Looper.java
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
// Looper 物件創建的時候,同時創建一個 MessageQueue
frameworks/base/core/java/android/os/Looper.java
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
通過上面的流程,主執行緒的 Looper、MessageQueue 都已經創建好了,這就打下了 Message 機制的基礎,后續有 Message 進來,就會進入主執行緒的 MessageQueue ,然后 Looper 會把他派發給對應的 Handler
對于主執行緒來說,這個 Handler 就在 ActivityThread 里面,下面截取一小段 Handler 的方法,大家可以看一下,熟悉代碼的應該知道,BIND_APPLICATION 就是大家經常在 Systrace 中看到的新行程啟動時候的那一段
frameworks/base/core/java/android/app/ActivityThread.java
class H extends Handler {
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int RECEIVER = 113;
public static final int CREATE_SERVICE = 114;
public static final int SERVICE_ARGS = 115;
public static final int STOP_SERVICE = 116;
public void handleMessage(Message msg) {
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
}
所以之前也有人會問,ActivityThread 是主執行緒么?為什么沒有繼承 Thread ?看了上面的流程,答案就很清楚了,ActivityThread 并不是一個 Thread ,只不過他有個叫 H 的 Handler 來處理主執行緒的 Message 而已;另外 Activity、Service、BroadcastReceiver 組件的生命周期都是在主執行緒執行的,通過上面的講解應該就比較好理解了:都是在 ActivityThread 的 H 這個 Handler 里面處理的.
執行緒間通信
App 主執行緒初始化完成后,Message 機制跑起來了,那么子執行緒呢?其實也是一樣的,子執行緒也有一套 Message 機制,有它自己的 MessageQueue、Looper、Handler,
那么執行緒間的 Message 通信就好理解了,Looper 在派發 Message 的時候,會根據 Message 自己的意愿(target,即目標 Handler),派發給對應的 Handler 去處理,這里的 Handler 既可以是子執行緒的 Handler ,也是主執行緒的 Handler,也可以是 App 行程里面其他的 Handler,只要知道且指定這個 Handler 即可
比如非常典型的一個例子就是 AsyncTask,如果你在主執行緒創建了 AsyncTask ,那么在 AsyncTask 執行在子執行緒完耗時任務后,就會給主執行緒的 Handler 發 Message,來更新主執行緒的 UI
子執行緒能不能更新 UI
既然主執行緒和子執行緒都是 Message 機制,子執行緒到底能不能更新 UI 呢?答案是可以的,但是會出問題,比如主執行緒正在執行 doFrame ,Measure 方法剛剛走完,你子執行緒把 View 的寬高給改掉了,那么主執行緒后續執行 Layout 的時候,View 的位置擺放就可能會出問題(當然我沒有試過,感興趣的小伙伴可以把 checkThread 限制代碼去掉,然后在子執行緒更新 UI 試試)
所以 Android 為了避免這種情況,在有 UI 更新的地方,都加了 checkThread() ,來確保只有主執行緒才能更新 UI
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
最后
關于如何學習Android Framework開發知識,最近有幸在前阿里技術總監手里扒到這份Android framework高級開發筆記,今天就拿出來分享給大家,
本筆記講解了Framework的主要模塊,從環境的部署到技術的應用,再到專案實戰,讓我們不僅是學習框架技術的使用,而且可以學習到使用架構如何解決實際的問題,由淺入深,詳細決議Framework,讓你簡單高效學完這塊知識!
如有需要獲取完整的資料檔案的朋友可以【點擊我】免費獲取,
第一章:深入決議Binder
Binder機制作為行程間通信的一種手段,基本上貫穿了andorid框架層的全部,所以首先必須要搞懂的Android Binder的基本通信機制,Binder機制作為行程間通信的一種手段,基本上貫穿了andorid框架層的全部,所以首先必須要搞懂的Android Binder的基本通信機制,
本章知識點
- Binder 系列—開篇
- Binder Driver 初探
- Binder Driver 再探
- Binder 啟動 ServiceManager
- 獲取 ServiceManager
- 注冊服務(addService)
- 獲取服務(getService)
- Framework 層分析
- 如何使用 Binder
- 如何使用 AIDL
- Binder 總結
- Binder 面試題全決議


第二章:深入決議Handler
本章先宏觀理論分析與 Message 原始碼分析,再到MessageQueue 的原始碼分析,Looper 的原始碼分析,handler 的原始碼分析,Handler 機制實作原理總結,最后還整理Handler 所有面試題大全決議,
Handler這章內容很長,但思路是循序漸進的,如果你能堅持讀完我相信肯定不會讓你失望,
本章知識點
- 宏觀理論分析與Message原始碼分析
- MessageQueue的原始碼分析
- Looper的原始碼分析
- handler的原始碼分析
- Handler機制實作原理總結
- Handler面試題全決議

第三章:Dalvik VM 行程系統
Andorid系統啟動、init 行程、Zygote、SystemServer啟動流程、 應用程式的創建使用,Activity的創建、銷毀 Handler和Looper,

第四章 深入決議 WMS
視窗管理框架 系統影片框架 View的作業原理,

第五章 PackagerManagerService
包管理服務,資源管理相關類,

如有需要獲取完整的資料檔案的朋友可以【點擊我】免費獲取,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/224832.html
標籤:其他
