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

Android Handler 消息機制:子執行緒更新 UI 變數主執行緒讀不到?用迴圈等待或回調

     編輯:程式設計綜合問答

問題現象

主執行緒啟動子執行緒查詢版本,Handler.handleMessage 收到訊息更新全域 newVersion,但主執行緒緊接著讀取仍為舊值。thread.join() 也無效。

根本原因

  • Handler 預設綁定建立它的執行緒 (主執行緒 Looper)。handleMessage 實際在主執行緒稍後透過 Looper.loop() 執行,非同步於 thread.start()。
  • thread.join() 僅等待子執行緒 run() 結束,不等待主執行緒訊息佇列處理。

解決方案

方案一:迴圈輪詢等待 (簡單但阻塞主執行緒,慎用)

while (newVersion == null) {
    try { Thread.sleep(100); } catch (InterruptedException ignored) {}
}
// 此時 newVersion 已更新

⚠️ 會凍結 UI,僅適用於啟動畫面等特定場景。

方案二:回調介面 (推薦,非阻塞)

interface VersionCallback {
    void onVersionReady(String version);
    void onError();
}

// 子執行緒
new Thread(() -> {
    String ver = checkVersionFromServer();
    new Handler(Looper.getMainLooper()).post(() -> {
        if (ver != null) callback.onVersionReady(ver);
        else callback.onError();
    });
}).start();

// 主執行緒實作介面
callback = new VersionCallback() {
    @Override public void onVersionReady(String v) { newVersion = v; updateUI(); }
    @Override public void onError() { showToast("檢查失敗"); }
};

方案三:Kotlin 協程 / RxJava / LiveData (現代架構)


// Coroutine
lifecycleScope.launch {
    val version = withContext(Dispatchers.IO) { checkVersion() }
    _newVersion.postValue(version) // LiveData 通知 UI
}

最佳實踐原則

  • 不要在主執行緒同步等待異步結果。
  • 用「回調/觀察者/協程」將異步結果傳遞回主執行緒繼續處理。
  • 全域變數跨執行緒訪問需 volatile 或 AtomicReference 保證可見性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved