You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Timer实现倒计时偶现负数显示异常问题求助

问题根因

出现负数倒计时是几个逻辑缺陷叠加导致的:

  • 计时器泄漏:调用startTimer()时没有先取消已有的旧Timer实例,只要重复触发启动逻辑,旧计时器就会在后台持续运行、多个实例同时修改计数,且mTimer仅保存最新实例,后续调用停止方法无法终止已泄漏的旧任务,计数会被持续扣减到负数,运行时间越长负数值越大,最终出现-03:-15这类跨分钟的负数显示。
  • 执行顺序错误:原有回调逻辑先递减计数、再更新UI、最后才判断是否归0停止,一旦Timer任务出现调度排队、cancel指令延迟生效的情况,计数归0后仍会继续被扣减。
  • 计数逻辑不可靠:靠每次回调给变量减1的方式计数,本身就会受Timer调度精度影响产生时间漂移,加上负数做除法、取模时不会自动转正,只要计数小于0就会显示负数格式。
  • 初始时间计算存在误差:初始剩余值在startTimer()调用瞬间计算,但Timer第一次回调默认有1000ms延迟,初始阶段就会出现计数和真实时间不匹配的问题。
修复方案

核心改动是抛弃手动递减计数的逻辑,改用目标时间戳差值计算剩余时间,从根源避免计数漂移、多扣问题,同时补上任务泄漏兜底、负数拦截逻辑,修复后代码如下:

import java.text.SimpleDateFormat
import java.util.*
import kotlin.concurrent.timer

private var mTimer: Timer? = null
// 记录本轮倒计时的截止时间戳
private var targetEndMillis = 0L

fun getNowTimeSecond() : String {
    val now: Long = System.currentTimeMillis()
    val date = Date(now)
    // 补全Locale参数,避免特殊地区格式异常
    val dateFormat = SimpleDateFormat("ss", Locale.getDefault())
    return dateFormat.format(date)
}

private fun startTimer() {
    // 启动新计时器前先终止旧任务,彻底避免泄漏
    stopTimer()
    // 计算本轮倒计时的截止时间点
    val initRemainSecond = 60 - getNowTimeSecond().toInt()
    targetEndMillis = System.currentTimeMillis() + initRemainSecond * 1000L

    mTimer = timer(period = 1000) {
        // 每次回调基于真实时间差算剩余值,不受调度精度影响
        val remainSecond = ((targetEndMillis - System.currentTimeMillis()) / 1000).toInt()
        // 剩余时间归0时更新显示后停止
        if (remainSecond <= 0) {
            _time.postValue("Time : 00:00")
            stopTimer()
            return@timer
        }
        // 此时remainSecond必然大于0,格式化不会出现负数
        val minuteStr = (remainSecond / 60).toString().padStart(2, '0')
        val secondStr = (remainSecond % 60).toString().padStart(2, '0')
        _time.postValue("Time : $minuteStr:$secondStr")
    }
}

private fun stopTimer() {
    mTimer?.cancel()
    mTimer = null
}

如果是在Android平台使用,更推荐用CountDownTimer或者协程delay实现倒计时,比原生Timer对生命周期的适配性更好。

内容的提问来源于stack exchange,提问作者Lucy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 03:57:32