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

Android 線程死循環與 Dead Code 分析:handler 異步更新導致判斷失效

     編輯:程式設計疑難解答

問題代碼

new Thread() {
    public void run() {
        try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
        while (hasData < 100) {
            progressStatus += (int)(Math.random() * 10);
            handler.sendEmptyMessage(0x123);
            // if (hasData >= 100) { Toast... } // 標註為 Dead Code
        }
    }
}.start();

Dead Code 成因三重奏

  1. 進不去循環:若初始 `hasData >= 100`,`while` 條件不成立,循環體零次執行,`if` 自然不執行。
  2. 死循環不出來:循環體**未修改 `hasData`**,`progressStatus` 遞增與 `hasData` 無關 → 永遠 `hasData < 100` → 無限循環 → 永遠執行不到循環後的 `if`(編譯器據此判定 `if` 為 Dead Code)。
  3. 異步更新時序不可控:即使 `handler` 處理消息時修改了 `hasData`,`handler` 運行在 **主線程**,當前線程繼續跑循環,**無法保證** `hasData` 在 `while` 判斷前被更新。即使更新了,也可能在 `if` 判斷前又被其他邏輯改回。

正確模式:單線程輪詢 或 線程間通信

方案一:單線程計數器(最簡單)

new Thread() {
    public void run() {
        int progress = 0;
        while (progress < 100) {
            try { Thread.sleep(100); } catch (InterruptedException ignored) {}
            progress += new Random().nextInt(10);
            if (progress >= 100) progress = 100;
            handler.obtainMessage(0x123, progress, 0).sendToTarget();
        }
    }
}.start();

方案二:主線程定時器驅動(無額外線程)

// 在 Activity/Fragment 中
int progress = 0;
Runnable updater = new Runnable() {
    @Override public void run() {
        progress += new Random().nextInt(10);
        if (progress >= 100) { progress = 100; showDone(); }
        else { textView.setText(progress + "%"); handler.postDelayed(this, 100); }
    }
};
handler.post(updater);

方案三:Kotlin 協程 / RxJava / Flow(現代化)

// Kotlin 協程
lifecycleScope.launch {
    var progress = 0
    while (progress < 100) {
        delay(100)
        progress += (1..10).random()
        progress = progress.coerceAtMost(100)
        _progressLiveData.postValue(progress) // 傳遞給 UI
    }
    showDone()
}

關鍵原則

  • **循環變量必須在循環內更新**,否則死循環。
  • **跨線程共享變量需同步**(`volatile`、`AtomicInteger`、`synchronized`),但首選**消息傳遞**而非共享內存。
  • **UI 更新必須在主線程**,`Handler`/`runOnUiThread`/`LiveData`/`Compose` 均可。

**Dead Code 警告是編譯器送的禮物,揭示了邏輯漏洞;修好邏輯,警告自然消失。**

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