很多Android初學者嘗試在主線程(UI線程)中`join()`或`wait()`等待子線程完成,這嚴重違背Android設計原則,會導致ANR(應用無響應)。本文解析錯誤原因並給出正確模式。
// ❌ 錯誤:主線程死等
Thread t = new Thread(() -> { /* 耗時任務 */ });
t.start();
try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); }
// 這裡主線程已卡死,UI凍結
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());
});
lifecycleScope.launch(Dispatchers.IO) {
val result = heavyWork()
withContext(Dispatchers.Main) {
textView.text = result.toString()
}
}
// 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更新,耗時任務拋給後台,結果通過回調/流/狀態返回主線程。