Android 單執行緒模型:UI 操作只能在主執行緒。耗時任務(網路、IO、計算)必須在子執行緒,完成後需將結果傳回主執行緒更新 UI。Handler-Looper-Message 正是官方提供的跨執行緒通訊標準機制。
what、obj、arg1/arg2、callback(Runnable)loop() 無限迴圈取出 Message 分派// ThreadLocal 確保每執行緒唯一 Looper
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
public static void prepare() {
if (sThreadLocal.get() != null)
throw new RuntimeException("Only one Looper per thread");
sThreadLocal.set(new Looper(true)); // 建立 Looper 並綁定 MessageQueue
}
public static void loop() {
Looper me = myLooper(); // 取得當前執行緒 Looper
MessageQueue queue = me.mQueue;
for (;;) { // 無限迴圈
Message msg = queue.next(); // 阻塞等待訊息
if (msg == null) return; // queue 退出
// 分派給目標 Handler
msg.target.dispatchMessage(msg);
// 回收 Message 物件(物件池模式)
msg.recycle();
}
}
public Handler() {
mLooper = Looper.myLooper(); // 取得當前執行緒 Looper
if (mLooper == null)
throw new RuntimeException("No Looper; prepare() not called");
mQueue = mLooper.mQueue; // 共享 MessageQueue
}
public boolean sendMessage(Message msg) {
return sendMessageDelayed(msg, 0);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this; // 關鍵:標記目標 Handler
return queue.enqueueMessage(msg, uptimeMillis);
}
public void dispatchMessage(Message msg) {
if (msg.callback != null) { // 1. post(Runnable) 回調
handleCallback(msg);
} else if (mCallback != null) { // 2. 建構子傳入 Callback
if (mCallback.handleMessage(msg)) return;
handleMessage(msg); // 3. 預設 handleMessage(子類別覆寫)
} else {
handleMessage(msg);
}
}
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain(); // 從物件池取得
m.callback = r; // 封裝 Runnable
return m;
}
dispatchMessage 發現 msg.callback != null 直接執行 handleCallback → 執行 r.run()。並未建立新執行緒,仍在 Looper 所屬執行緒(通常是主執行緒)執行。
new Thread() {
Handler handler;
@Override public void run() {
Looper.prepare(); // 1. 建立 Looper
handler = new Handler() {
@Override public void handleMessage(Message msg) {
// 處理訊息,執行緒為此子執行緒
}
};
Looper.loop(); // 2. 開啟迴圈
}
}.start();
其他執行緒可透過此 handler 發送訊息,處理邏輯將在該子執行緒執行。
| 風險 | 原因 | 解決方案 |
|---|---|---|
| 非靜態內部類 Handler 持有外部類引用 | Message 延遲執行導致 Activity 無法 GC | 靜態內部類 + WeakReference<Activity> |
| delayed 訊息未移除 | Activity 銷毀前未 removeCallbacksAndMessages(null) | onDestroy() 統一清理 |
| 靜態 Handler 持有 Context | 同樣導致洩漏 | 避免靜態持有 Context,或使用 Application Context |
withContext(Dispatchers.Main) 取代 HandlerlifecycleScope.launch 自動取消Handler-Looper-Message 是 Android 核心基礎設施,理解其「單執行緒循環 + 訊息佇列 + 目標分派」架構,能深度掌握跨執行緒通訊本質。雖現代開發推薦協程與反應式框架,但閱讀源碼、除錯 ANR、分析第三方庫行為時,這套機制知識不可或缺。