CountDownTimer暂停恢复导致进度条负数问题求助
解决CountDownTimer暂停恢复后进度条负数问题
问题根源
- 回调延迟导致误差累积:系统调度延迟会让
onTick回调不精准,暂停时直接cancel并记录理论剩余时间,恢复后累计误差会让剩余时间计算出现负数。 - 剩余时间记录不精准:暂停时未基于最新
onTick回调值更新剩余时间,而是用初始计算值,导致恢复后倒计时逻辑偏离实际时长。 - 无数值边界校验:更新进度条时未判断数值是否小于0,直接赋值导致负数显示。
修复方案
自定义可暂停恢复的倒计时器,精准维护剩余时间,同时给进度条数值加边界校验:
自定义可暂停倒计时器代码
class PausableCountDownTimer( private val totalMillis: Long, private val intervalMillis: Long, private val onTickAction: (remaining: Long) -> Unit, private val onFinishAction: () -> Unit ) { private var remainingMillis = totalMillis private var isPaused = false private var internalTimer: CountDownTimer? = null // 启动/重启倒计时 fun start() { isPaused = false internalTimer?.cancel() internalTimer = object : CountDownTimer(remainingMillis, intervalMillis) { override fun onTick(millisUntilFinished: Long) { if (!isPaused) { remainingMillis = millisUntilFinished onTickAction.invoke(remainingMillis) } } override fun onFinish() { remainingMillis = 0 onFinishAction.invoke() } }.start() } // 暂停倒计时 fun pause() { isPaused = true internalTimer?.cancel() } // 恢复倒计时 fun resume() { if (isPaused && remainingMillis > 0) { start() } } // 重置倒计时 fun reset() { internalTimer?.cancel() remainingMillis = totalMillis isPaused = false } }
页面使用示例
class TimerActivity : AppCompatActivity() { private lateinit var timerProgress: ProgressBar private lateinit var pausableTimer: PausableCountDownTimer // 总时长60秒,间隔1秒更新 private val TOTAL_TIME = 60000L private val UPDATE_INTERVAL = 1000L override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_timer) timerProgress = findViewById(R.id.timer_progress) timerProgress.max = (TOTAL_TIME / 1000).toInt() // 初始化自定义倒计时器 pausableTimer = PausableCountDownTimer(TOTAL_TIME, UPDATE_INTERVAL, onTickAction = { remaining -> val progress = (remaining / 1000).toInt() // 强制进度不小于0,避免负数显示 timerProgress.progress = maxOf(progress, 0) }, onFinishAction = { timerProgress.progress = 0 Toast.makeText(this, "倒计时结束", Toast.LENGTH_SHORT).show() } ) // 绑定按钮事件 findViewById<Button>(R.id.btn_start).setOnClickListener { pausableTimer.start() } findViewById<Button>(R.id.btn_pause).setOnClickListener { pausableTimer.pause() } findViewById<Button>(R.id.btn_resume).setOnClickListener { pausableTimer.resume() } findViewById<Button>(R.id.btn_reset).setOnClickListener { pausableTimer.reset() } } override fun onDestroy() { super.onDestroy() pausableTimer.reset() } }
关键优化点
- 精准维护剩余时间:每次
onTick回调时更新remainingMillis,确保暂停时记录的是最新剩余时长。 - 暂停时终止计时器:暂停时cancel内部的CountDownTimer,避免后台回调干扰剩余时间计算。
- 边界校验:更新进度条时用
maxOf(progress, 0)强制数值不小于0,彻底解决负数显示问题。
内容的提问来源于stack exchange,提问作者Chayan
相关产品推荐
相关产品推荐

