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

Fragment销毁时计时器重置:如何实现类似Google Authenticator的持久计时器

实现持久化循环计时器(类似Google Authenticator)

你当前用CountDownTimer的问题在于,它是内存级别的计时——一旦Fragment销毁、进程被回收,计时器的状态就会丢失,重启后只能重新开始。而Google Authenticator这类计时器的核心逻辑是基于系统绝对时间的无状态计算,不依赖内存中的定时器实例,所以能在任何场景下恢复正确的计时。

解决方案思路

  • 定义固定的计时周期(比如你原本的10秒)
  • 每次需要获取剩余时间时,用当前系统时间对周期取模,计算出距离下一个周期结束的剩余时长
  • 结合Fragment生命周期,用定时任务(协程/Handler)刷新UI,避免内存泄漏

代码实现(Kotlin 协程版)

class YourFragment : Fragment() {
    // 计时周期:和你原来的CountDownTimer保持一致,10秒
    private val cycleDuration = 10000L
    // 控制协程的Job,用于在Fragment不可见时停止刷新
    private var timerJob: Job? = null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 初始化时立即更新一次UI
        updateTimerDisplay()
    }

    override fun onResume() {
        super.onResume()
        // 启动每秒一次的UI刷新
        timerJob = lifecycleScope.launch {
            while (isActive) {
                updateTimerDisplay()
                delay(1000)
            }
        }
    }

    override fun onPause() {
        super.onPause()
        // 停止协程,避免内存泄漏
        timerJob?.cancel()
    }

    private fun updateTimerDisplay() {
        // 核心逻辑:基于系统绝对时间计算剩余时长
        val currentTime = System.currentTimeMillis()
        val elapsedInCycle = currentTime % cycleDuration
        val remainingTime = cycleDuration - elapsedInCycle
        
        // 转换为秒数并更新UI(示例)
        val secondsLeft = remainingTime / 1000
        // textView.text = "$secondsLeft"
    }
}

关键逻辑说明

  • System.currentTimeMillis()是系统的绝对时间,即使应用被杀重启,这个时间也是连续的,不会中断
  • currentTime % cycleDuration能算出当前周期内已经流逝的时间,用周期总时长减去它,就能得到准确的剩余时间
  • 用lifecycleScope启动协程,会自动跟随Fragment的生命周期,无需手动处理内存泄漏问题;如果用Handler实现,记得在onPause中调用removeCallbacks停止任务

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 12:50:15