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

Flutter Timer.periodic 5秒与5000毫秒定时器运行速度不一致问题

定时器计时不一致问题原因及解决方案

问题根因

  • Timer.periodic是基于Dart事件循环调度的软定时器,无法保证回调严格按照设定的间隔触发,尤其是间隔小于16ms的定时器,受平台事件循环最小调度粒度(通常为10~16ms,和系统屏幕刷新帧率对齐)限制,实际触发间隔会远大于设定的1ms。
  • 计时逻辑存在设计缺陷:你依赖定时器回调的次数来扣减剩余时间,触发频率不足就会直接导致计时变慢。你设置的1ms间隔定时器要触发5000次才会结束,按实际最小触发间隔10ms计算,5000次最少需要50秒才能跑完,自然比只需要触发5次的1秒间隔定时器慢得多。
  • 另外你贴出的代码存在语法错误,Duration的构造参数需要包裹在括号内,正确写法为Duration(seconds: 1)。

修复方案

不要通过回调次数累加计算时长,改为记录启动时间戳,每次回调时用当前时间戳减去启动时间戳得到已过时长,再计算剩余时间,这种方式的计时精度只和系统时钟有关,不受定时器调度间隔影响。
示例代码如下:

int totalSec = 5;
int totalMilSec = 5000;
int timeLeftSec = 5;
int timeLeftMilSec = 5000;
DateTime? startTimeSec;
DateTime? startTimeMil;

onPressed: (){
  // 秒级定时器
  startTimeSec = DateTime.now();
  Timer.periodic(const Duration(seconds: 1), (timer){
    final passed = DateTime.now().difference(startTimeSec!).inSeconds;
    if(passed < totalSec){
      timeLeftSec = totalSec - passed;
    }else{
      timeLeftSec = 0;
      timer.cancel();
    }
  });

  // 毫秒级定时器
  startTimeMil = DateTime.now();
  Timer.periodic(const Duration(milliseconds: 10), (timer){
    final passed = DateTime.now().difference(startTimeMil!).inMilliseconds;
    if(passed < totalMilSec){
      timeLeftMilSec = totalMilSec - passed;
    }else{
      timeLeftMilSec = 0;
      timer.cancel();
    }
  });
}

注意:不需要设置1ms这么小的定时器间隔,一般UI更新最高只需要和屏幕刷新率对齐,设置10~16ms的间隔就足够,更小的间隔只会浪费性能,不会提升任何显示精度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 11:36:06