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

Flutter计时器快速点击播放/暂停倒计时加速问题修复咨询

解决Flutter倒计时快速点击播放/暂停导致加速的问题

你的推测完全正确:快速点击按钮时,每次调用toggleTimer()都会创建新的Timer.periodic实例,多个定时器同时触发倒计时逻辑,导致时间减少速度翻倍。

修正方案

核心思路是持有单个定时器实例的引用,确保同一时间只有一个定时器在运行,每次启动新定时器前先取消已存在的实例:

  1. 在State类中添加Timer?类型变量,用于保存当前定时器
  2. 重构toggleTimer()方法,启动前先清理旧定时器
  3. 优化播放/暂停的状态逻辑,保持状态与定时器操作同步
  4. 在组件销毁时取消定时器,避免内存泄漏

修改后的完整代码

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:quickrest/styles/text_styles.dart';
import 'package:quickrest/styles/color_styles.dart';
import 'package:liquid_progress_indicator/liquid_progress_indicator.dart';

class ActiveTimerScreen extends StatefulWidget {
  const ActiveTimerScreen({super.key, required this.seconds});

  final int seconds;

  @override
  State<ActiveTimerScreen> createState() => _ActiveTimerScreenState();
}

class _ActiveTimerScreenState extends State<ActiveTimerScreen> {
  int _timeLeft = 0;
  bool timerStarted = false;
  // 新增:持有当前定时器引用
  Timer? _timer;

  @override
  void initState() {
    super.initState();
    _timeLeft = widget.seconds;
    timerStarted = true;
    toggleTimer();
  }

  @override
  void dispose() {
    // 组件销毁时取消定时器
    _timer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: SafeArea(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            const SizedBox(width: double.infinity),
            Padding(
              padding: EdgeInsets.only(
                top: MediaQuery.of(context).size.height * 0.3,
              ),
              child: Text(
                '${_timeLeft ~/ 60} : ${(_timeLeft % 60).toString().padLeft(2, '0')}',
                style: activeTimerTitleTextStyle,
              ),
            ),
            Padding(
              padding: const EdgeInsets.only(
                top: 80.0,
              ),
              child: ElevatedButton(
                style: ElevatedButton.styleFrom(
                  shape: const CircleBorder(),
                  backgroundColor: Colors.black,
                ),
                onPressed: () {
                  setState(() {
                    timerStarted = !timerStarted;
                    toggleTimer();
                  });
                },
                child: Padding(
                  padding: const EdgeInsets.all(4.0),
                  child: Icon(
                    !timerStarted ? Icons.play_arrow : Icons.pause,
                    size: 100,
                  ),
                ),
              ),
            ),
            Padding(
              padding: const EdgeInsets.only(top: 80.0),
              child: OutlinedButton(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                style: OutlinedButton.styleFrom(
                  backgroundColor: Colors.white,
                  side: const BorderSide(
                    color: Colors.white,
                  ),
                  shape: const RoundedRectangleBorder(
                    borderRadius: BorderRadius.all(
                      Radius.circular(24),
                    ),
                  ),
                ),
                child: const Text(
                  "Cancel",
                  style: activeTimerCancelTextStyle,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  void toggleTimer() {
    const oneSec = Duration(seconds: 1);
    // 先取消已存在的定时器,避免多个实例同时运行
    _timer?.cancel();
    
    if (timerStarted && _timeLeft > 0) {
      _timer = Timer.periodic(oneSec, (Timer t) {
        setState(() {
          if (_timeLeft <= 1) {
            t.cancel();
            timerStarted = false;
            _timeLeft = 0;
          } else {
            _timeLeft -= 1;
          }
        });
      });
    }
  }
}

关键修改说明

  • 新增Timer? _timer变量,跟踪当前活跃的定时器实例
  • 在toggleTimer()开头先调用_timer?.cancel(),确保启动新定时器前旧的已经被销毁
  • 重构按钮点击逻辑,直接切换timerStarted状态后调用toggleTimer(),逻辑更简洁
  • 在dispose()中取消定时器,防止组件销毁后定时器仍在后台运行导致内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 13:35:19