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

Android線程同步:為什黠主線程不應死等子線程及正確替代方案

     編輯:程式設計綜合問答

很多Android初學者嘗試在主線程(UI線程)中`join()`或`wait()`等待子線程完成,這嚴重違背Android設計原則,會導致ANR(應用無響應)。本文解析錯誤原因並給出正確模式。

為什麼主線程不能阻塞?

  • 主線程專責UI繪製、事件分發、用戶交互響應。
  • 阻塞超過5秒即觸發ANR對話框,用戶體驗極差。
  • Android系統不允許主線程進行耗時操作(網絡、IO、複雜計算)。

錯誤代碼示例

// ❌ 錯誤:主線程死等
Thread t = new Thread(() -> { /* 耗時任務 */ });
t.start();
try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); }
// 這裡主線程已卡死,UI凍結

正確異步模式:回調/接口/協程

1. 接口回調(傳統Java)

public interface OnTaskFinishListener {
    void onFinish(Result result);
}

void doTask(OnTaskFinishListener listener) {
    new Thread(() -> {
        Result result = heavyWork();
        runOnUiThread(() -> listener.onFinish(result));
    }).start();
}

// 調用
doTask(result -> {
    // 更新UI
    textView.setText(result.toString());
});

2. Kotlin協程(現代首選)

lifecycleScope.launch(Dispatchers.IO) {
    val result = heavyWork()
    withContext(Dispatchers.Main) {
        textView.text = result.toString()
    }
}

3. LiveData/Flow + ViewModel(架構組件)

// ViewModel
val resultLiveData = MutableLiveData()
fun loadData() {
    viewModelScope.launch(Dispatchers.IO) {
        resultLiveData.postValue(heavyWork())
    }
}

// Activity/Fragment
viewModel.resultLiveData.observe(viewLifecycleOwner) { result ->
    textView.text = result.toString()
}

特殊場景處理

若必須在子線程完成前阻塞當前線程(如IntentService、同步初始化),請在子線程中執行阻塞邏輯,或使用`CountDownLatch`/`CompletableFuture`配合線程池,絕不在主線程操作。

核心心法:主線程只負責分發與UI更新,耗時任務拋給後台,結果通過回調/流/狀態返回主線程。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved