带ProgressBar的CountDownTimer重启应用后如何接续进度
问题修复方案
你原来的实现有两个核心问题:
- 使用了
startCountdown方法内的局部变量i计数,每次调用方法、每次重启应用i都会被重置为1,完全无法对应之前已经走完的倒计时时长,这也是你替换40000变量不生效的核心原因 - 进度计算逻辑错误,没有基于「已执行时长 = 总时长 - 剩余时长」的比例计算,硬编码总时长导致灵活性差
修复步骤
- 先抽离全局常量,统一管理总倒计时时长,避免硬编码,同时你已经有的
timeLeftInMilliseconds要声明为全局变量,在onStart生命周期里从SharedPreferences读取持久化的值,读取不到就默认设为总时长
// 全局声明,总倒计时固定为40秒 private val TOTAL_COUNTDOWN_MILLIS = 40000L // 全局存储剩余倒计时毫秒数 private var timeLeftInMilliseconds = TOTAL_COUNTDOWN_MILLIS // 全局持有CountDownTimer实例,方便退出时取消避免内存泄漏 private var countDownTimer: CountDownTimer? = null
- 删掉局部计数变量
i,直接用剩余时长和总时长的比例计算进度,启动倒计时前先计算初始进度赋值给ProgressBar,避免启动后第一秒进度为0的问题,修改后的startCountdown实现如下:
private fun startCountdown() { // 先设置初始进度,应用启动后立刻显示正确进度 val initProgress = ((TOTAL_COUNTDOWN_MILLIS - timeLeftInMilliseconds) * 100 / TOTAL_COUNTDOWN_MILLIS).toInt() myProgressBar.progress = initProgress // 先取消之前可能存在的倒计时实例,避免重复执行 countDownTimer?.cancel() countDownTimer = object : CountDownTimer(timeLeftInMilliseconds, 1000) { override fun onTick(millisUntilFinished: Long) { timeLeftInMilliseconds = millisUntilFinished // 直接用时间差计算进度,不需要额外计数变量 val progress = ((TOTAL_COUNTDOWN_MILLIS - millisUntilFinished) * 100 / TOTAL_COUNTDOWN_MILLIS).toInt() myProgressBar.progress = progress } override fun onFinish() { myProgressBar.progress = 100 timeLeftInMilliseconds = TOTAL_COUNTDOWN_MILLIS } }.start() }
- 补充
onStop里的执行逻辑,退出页面时先取消倒计时再存剩余时间,避免存到错误的中间值:
override fun onStop() { super.onStop() countDownTimer?.cancel() // 此处将timeLeftInMilliseconds写入SharedPreferences持久化即可 }
内容的提问来源于stack exchange,提问作者The Fluffy T Rex
相关产品推荐
相关产品推荐

