溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

handler的執行順序是怎么樣的

發布時間:2021-12-16 16:43:54 來源:億速云 閱讀:404 作者:iii 欄目:云計算
# Handler的執行順序是怎么樣的

## 引言

在Android開發中,`Handler`作為線程間通信的核心組件,其執行順序直接影響著消息處理的正確性和性能表現。本文將深入剖析Handler的消息處理機制,從消息入隊到最終執行的完整流程,幫助開發者掌握Handler的工作時序,避免常見的時序錯誤。

## 一、Handler基礎架構回顧

### 1.1 核心組件關系
```java
// 典型Handler使用示例
Handler handler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        // 處理消息
    }
};

Android消息機制由三大核心組件構成: - MessageQueue:消息存儲隊列(單鏈表實現) - Looper:消息循環泵,負責從隊列提取消息 - Handler:消息處理器,承擔發送和處理雙重角色

1.2 消息循環流程

發送端Handler -> MessageQueue.enqueueMessage()
           ↓
Looper.loop() -> MessageQueue.next()
           ↓
目標Handler.dispatchMessage()

二、消息入隊順序分析

2.1 同步發送時序

handler.sendMessage(msg1);
handler.sendMessage(msg2);
// 執行順序:msg1 → msg2

同步發送時,消息按調用順序嚴格進入隊列尾部,形成FIFO(先進先出)結構。這種順序在單線程環境下絕對可靠。

2.2 異步消息的特殊性

Message msg = Message.obtain();
msg.setAsynchronous(true);  // 標記為異步消息
handler.sendMessage(msg);

異步消息(通過setAsynchronous(true)標記)在API 16+引入,主要用于系統級高優先級消息(如VSync事件),但在普通消息隊列中仍按入隊時間排序。

2.3 延遲消息的隊列插入

handler.sendMessageDelayed(msg1, 1000);  // 1秒延遲
handler.sendMessage(msg2);               // 立即發送

延遲消息通過when字段記錄目標執行時間: 1. 消息入隊時根據SystemClock.uptimeMillis() + delay計算when 2. MessageQueue按when值升序排列 3. 即使后發送的msg2也會因更小的when值排在msg1前

三、消息出隊處理順序

3.1 Looper的提取邏輯

// 偽代碼展示Native層消息提取
Message next() {
    for (;;) {
        nativePollOnce(ptr, timeout);
        synchronized (this) {
            Message prev = null;
            Message msg = mMessages;
            // 尋找符合條件的消息
            if (msg != null && msg.when <= now) {
                // 出隊操作...
                return msg;
            }
        }
    }
}

關鍵處理規則: 1. 總是取隊列頭部滿足when <= currentTime的消息 2. 遇到未到時的消息會進入native休眠 3. 新消息插入頭部時會觸發native喚醒

3.2 屏障消息(Barrier)機制

// 系統內部使用代碼
mQueue.postSyncBarrier();

特殊場景下的順序調整: 1. 同步屏障(token != 0的消息)會阻塞后續同步消息 2. 只有異步消息能越過屏障處理 3. 屏障移除后恢復同步消息處理 4. 典型應用場景:ViewRootImpl的繪制流程

四、消息分發優先級

4.1 dispatchMessage的三級處理

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);  // 1.優先處理Runnable
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {  // 2.其次處理Callback
                return;
            }
        }
        handleMessage(msg);  // 3.最后調用Handler方法
    }
}

處理優先級從高到低: 1. Message自帶的Runnable(通過post()系列方法發送) 2. Handler構造時傳入的Callback接口 3. Handler子類重寫的handleMessage()

4.2 典型時序沖突案例

Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        // 可能永遠不會執行
    }
};

// 發送Runnable會覆蓋同名Message處理
handler.post(() -> {...});
handler.sendEmptyMessage(0);

五、多Handler場景下的競爭

5.1 共享Looper的競爭

// 同一線程創建多個Handler
Handler handler1 = new Handler();
Handler handler2 = new Handler();

handler1.sendMessage(msg1);
handler2.sendMessage(msg2);

雖然Handler不同,但共享同一個MessageQueue: - 消息仍然嚴格按時序排列 - 處理時根據Message.target字段路由到對應Handler

5.2 跨線程發送的時序風險

// 線程A
handlerB.sendMessage(msg);

// 線程B的Handler
Handler handlerB = new Handler(threadBLooper) {...}

跨線程發送存在潛在問題: 1. 發送操作線程安全(通過synchronized保證) 2. 但無法保證目標線程的處理速度 3. 可能產生”發送早卻處理晚”的現象

六、特殊API對順序的影響

6.1 sendMessageAtFrontOfQueue

handler.sendMessageAtFrontOfQueue(msg);

強制插入隊列頭部的注意事項: 1. 消息會跳過所有未執行的普通消息 2. 但不能越過同步屏障 3. 濫用可能導致消息饑餓

6.2 removeMessages系列

handler.removeMessages(WHAT_CODE);

消息移除的邊界條件: 1. 只能移除尚未開始處理的消息 2. 正在dispatch的消息無法取消 3. 批量移除時按隊列順序掃描

七、實戰問題排查指南

7.1 消息堆積診斷

adb shell dumpsys activity processes | grep -A10 "Message Queue"

通過系統工具檢測: - 檢查隊列深度(pending消息數量) - 分析延遲消息的when值 - 識別阻塞的同步屏障

7.2 順序錯亂常見原因

  1. 錯誤假設跨線程發送順序
  2. 混淆post()與sendMessage()
  3. 未考慮設備休眠對uptimeMillis的影響
  4. 同步屏障未正確移除

八、性能優化建議

8.1 消息合并技巧

// 替代多次sendMessage
handler.removeMessages(WHAT_UPDATE);
handler.sendEmptyMessage(WHAT_UPDATE);

適用場景: - 頻繁觸發的UI更新 - 狀態同步事件 - 進度報告消息

8.2 延遲消息優化

// 避免短間隔延遲消息鏈
handler.sendMessageDelayed(msg, interval);

// 改為計算絕對時間
long nextTime = lastTime + interval;
handler.sendMessageAtTime(msg, nextTime);

結語

理解Handler的執行順序需要掌握三個維度: 1. 時間維度:when值的計算與比較 2. 空間維度:在MessageQueue中的物理排列 3. 邏輯維度:dispatchMessage的路由策略

正確運用這些知識,可以構建出高效可靠的Android消息系統。建議開發者通過Looper.loop()源碼和MessageQueue.next()的Native實現進行深入學習。

本文基于Android 13源碼分析,關鍵類路徑: - frameworks/base/core/java/android/os/Handler.java - frameworks/base/core/java/android/os/MessageQueue.java - frameworks/base/core/java/android/os/Looper.java “`

(全文約3450字,滿足Markdown格式要求)

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女