????Handler 是 Android 中實現(xiàn)線程間通信的核心類,主要用于在不同線程(如主線程與子線程)之間發(fā)送和處理消息。它是 Android 消息機制的核心組件,理解其原理對開發(fā)高性能應用至關重要。
一、核心組件與協(xié)作關系
Handler
????作用:發(fā)送消息 (sendMessage) 和處理消息 (handleMessage)。
????綁定關系:每個 Handler 必須關聯(lián)一個線程的 Looper(默認綁定當前線程的 Looper)。
Looper
????作用:循環(huán)從 MessageQueue 中取出消息,分發(fā)給對應的 Handler 處理。
關鍵方法:
????Looper.prepare():初始化當前線程的 Looper。
????Looper.loop():啟動消息循環(huán)。
????主線程 Looper:由系統(tǒng)自動創(chuàng)建,開發(fā)者無需手動調用 prepare()。
MessageQueue
????作用:存儲待處理的消息(單鏈表結構,按時間排序)。
????線程唯一性:每個線程最多一個 MessageQueue,由 Looper 管理。
Message
????作用:消息的載體,包含 what(標識)、arg1/arg2(簡單數(shù)據)、obj(復雜對象)等字段。
????優(yōu)化建議:使用 Message.obtain() 復用消息對象,避免內存抖動。
二、工作原理流程圖
+----------------+ +----------------+ +-------------------+
| Handler | ----> | MessageQueue | <---- | Looper |
| (sendMessage) | | (enqueueMessage)| | (loop() 輪詢取消息) |
+----------------+ +-------------------+ +-------------------+
↑ |
| ↓
+----------------+ +-------------------+
| 子線程/主線程 | | Handler |
| (觸發(fā)消息發(fā)送) | | (handleMessage()) |
+----------------+ +-------------------+
????發(fā)送消息:Handler 通過 sendMessage() 或 post(Runnable) 將消息插入 MessageQueue。
????輪詢消息:Looper 不斷調用 MessageQueue.next() 取出下一條消息(若無消息則阻塞)。
????分發(fā)處理:Looper 將消息分發(fā)給目標 Handler,執(zhí)行其 handleMessage() 或 Runnable。
三、關鍵代碼示例
// 主線程中創(chuàng)建 Handler(自動關聯(lián)主線程 Looper)
Handler mainHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
// 處理主線程消息(如更新 UI)
}
};
// 子線程中使用 Handler
new Thread(() -> {
Looper.prepare(); // 初始化子線程 Looper
Handler threadHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 處理子線程消息
}
};
Looper.loop(); // 啟動消息循環(huán)
}).start();
// 發(fā)送消息示例
mainHandler.sendEmptyMessage(1); // 發(fā)送空消息
mainHandler.post(() -> { /* 執(zhí)行 Runnable */ }); // 發(fā)送 Runnable
四、使用場景與最佳實踐
主線程更新 UI
????子線程處理完耗時任務后,通過 Handler 通知主線程更新 UI。
new Thread(() -> {
// 子線程執(zhí)行耗時操作
String result = fetchDataFromNetwork();
mainHandler.post(() -> textView.setText(result)); // 切回主線程更新 UI
}).start();
定時任務與延遲執(zhí)行
????使用 postDelayed() 實現(xiàn)定時操作(如輪詢、動畫)。
handler.postDelayed(() -> {
// 延遲 1 秒執(zhí)行
}, 1000);
跨線程通信
????多個線程通過 Handler 共享數(shù)據或協(xié)調任務。
避免內存泄漏
????問題:非靜態(tài)內部類 Handler 隱式持有外部類(如 Activity)引用,若 Activity 銷毀時仍有未處理消息,會導致內存泄漏。
解決方案:
????使用靜態(tài)內部類 + WeakReference。
????在 onDestroy() 中調用 handler.removeCallbacksAndMessages(null) 移除所有消息。
五、常見問題與解決
子線程中創(chuàng)建 Handler 崩潰
????錯誤日志:Can't create handler inside thread that has not called Looper.prepare()
????原因:子線程未初始化 Looper。
????解決:調用 Looper.prepare() 和 Looper.loop()。
主線程 Looper 的初始化時機
????答案:在應用啟動時,系統(tǒng)通過 ActivityThread.main() 調用 Looper.prepareMainLooper() 初始化主線程 Looper。
消息同步屏障(Sync Barrier)
????作用:優(yōu)先處理異步消息(如 UI 繪制消息 VSYNC),通過 postSyncBarrier() 插入屏障。
????應用場景:確保高優(yōu)先級消息及時處理。
HandlerThread 的使用
????定位:自帶 Looper 的子線程,簡化 Handler 在子線程中的使用。
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
六、與其他異步機制的對比
| 機制 | 特點 | 適用場景 |
|---|---|---|
| Handler | 靈活、底層,需手動管理消息隊列和線程切換 | 跨線程通信、定時任務、UI 更新 |
| AsyncTask | 封裝簡化,但易內存泄漏,已廢棄 | 簡單后臺任務(不推薦新項目使用) |
| RxJava | 響應式編程,鏈式調用,強大的線程切換和錯誤處理 | 復雜異步流、事件組合 |
| Coroutines | 輕量級協(xié)程,結構化并發(fā),代碼簡潔 | 現(xiàn)代 Android 開發(fā)的首選異步方案 |
七、總結
????核心角色:Handler 是 Android 消息機制的樞紐,負責跨線程通信和任務調度。
????關鍵點:理解 Looper、MessageQueue 的協(xié)作,避免內存泄漏,合理選擇異步方案。
????演進:隨著 Kotlin 協(xié)程的普及,直接使用 Handler 的場景減少,但其底層原理仍至關重要(如協(xié)程的 Dispatchers.Main 內部依賴 Handler)。