首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Android 主線程與子線程通信:Handler 機制深度解析

     編輯:程式設計疑難解答

核心結論

子線程向主線程發送消息,直接使用主線程的 Handler 實例即可,無需在子線程創建 Looper/Handler。 主線程(UI 線程)啟動時自動調用 Looper.prepareMainLooper() 並進入 Looper.loop(),因此天然擁有消息循環能力。

標準通信模式

1. 主線程 → 子線程(任務分發)

// 主線程持有子線程的 Handler
Handler workerHandler = new Handler(workerThread.getLooper());

// 發送任務
workerHandler.post(() -> {
    // 這裡運行在子線程
    doBackgroundWork();
});

2. 子線程 → 主線程(UI 更新)

// 主線程創建 Handler(關聯主線程 Looper)
Handler mainHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(@NonNull Message msg) {
        // 這裡運行在主線程,安全更新 UI
        updateUI(msg);
    }
};

// 子線程中直接使用主線程 Handler
new Thread(() -> {
    // 耗時操作...
    Message msg = mainHandler.obtainMessage(WHAT_UPDATE, result);
    msg.sendToTarget();  // 或 mainHandler.sendMessage(msg)
}).start();

為什麼不需要在子線程創建 Looper?

  • Handler.sendMessage() 只是將 Message 推入目標 MessageQueue,不關心發送者是哪個線程。
  • 消息處理邏輯 handleMessage() 執行於 Looper.loop() 所在線程,由目標 Handler 的 Looper 決定。
  • 主線程已有 Looper 且持續循環,天然適合作為 UI 更新的消費端。

一個 Looper 對應多個 Handler 的意義

同一線程可創建多個 Handler,分別處理不同業務消息(如 UI_HANDLER、NETWORK_HANDLER),通過 what 區分消息類型,實現邏輯解耦。所有 Handler 共享同一 MessageQueue,由同一 Looper 依次分發。

進階:HandlerThread 簡化子線程 Looper 創建

HandlerThread workerThread = new HandlerThread("Worker");
workerThread.start();
// 獲取綁定該線程 Looper 的 Handler
Handler workerHandler = new Handler(workerThread.getLooper());

// 使用完畢釋放
workerThread.quitSafely();  // API 18+

常見坑點避坑指南

錯誤做法後果正確做法
子線程 new Handler() 無參構造綁定當前線程 Looper,若未 prepare() 崩潰傳入 Looper.getMainLooper() 或 workerThread.getLooper()
主線程執行耗時操作ANR(Application Not Responding)耗時操作拋給子線程,結果回主線程 Handler
Activity 銷毀後 Handler 持有引用內存洩漏、UI 更新崩潰使用靜態內部類 + WeakReference,或 removeCallbacksAndMessages(null)

總結

Android 線程通信本質是「生產者將消息投遞到消費者的消息隊列」。主線程自帶 Looper,是天然的消費者;子線程若需接收消息,需自備 Looper(推薦 HandlerThread)。掌握「誰的 Looper,誰的線程執行 handleMessage」核心原理,即可靈活設計各類異步協作場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved