現象:使用 Handler 定時更新 SeekBar,但 UI 其他元素凍結、響應極慢。
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
int pos = setProgress(); // 更新 SeekBar
if (!mDragging && mBoundService.isPlaying()) {
// 錯誤:100 - (pos % 1000) 極大概率為負數或極小值
msg = obtainMessage(SHOW_PROGRESS);
sendMessageDelayed(msg, 100 - (pos % 1000)); // 這裡!
}
}
};
pos % 1000 範圍 0~999。100 - (pos % 1000) 範圍 -899 ~ 100。// 正確:1000 - (pos % 1000) → 下一個整秒邊界
sendMessageDelayed(msg, 1000 - (pos % 1000));
若 pos 為毫秒進度,則 pos % 1000 為當前秒內毫秒數,1000 - ... 為距離下一秒的毫秒數,實現「每秒整點更新」。
// 發送前移除舊消息,避免重複排隊
mHandler.removeMessages(SHOW_PROGRESS);
mHandler.sendMessageDelayed(msg, 1000 - (pos % 1000));
// Kotlin 協程
lifecycleScope.launch {
while (isPlaying) {
val pos = boundService.currentPosition
val delay = 1000 - (pos % 1000)
delay(delay)
_seekProgress.postValue(pos) // LiveData 觸發 UI 更新
}
}
一個減法符號錯誤(100 vs 1000)導致主線程消息風暴。**定時更新 UI 必須確保延遲 ≥ 16ms (理想 ≥ 200ms)**,並清理舊消息。