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

Flutter日期倒计时问题:天数显示错误与计时速度异常

Flutter倒计时器问题修复

问题原因分析

  1. 天数显示错误:原代码计算天数时多了%24,导致超过24天的数值被取模,无法正确显示真实剩余天数。
  2. 计时速度过快:Timer在build方法中创建,每次setState都会生成新的Timer实例,多个Timer同时触发减1操作,导致计时速度异常;同时未在dispose中销毁Timer,存在内存泄漏风险。

修复后的完整代码

import 'dart:async';
import 'package:flutter/material.dart';

class Time extends StatefulWidget {
  const Time({Key? key}) : super(key: key);

  @override
  State<Time> createState() => _TimeState();
}

final eventTime = DateTime.parse('2024-01-10 03:41:00');
class _TimeState extends State<Time> {

  static const duration = Duration(seconds: 1);
  late int timeDiff;
  late Timer timer;
  bool isActive = true;

  void handleTick() {
    if (isActive) {
      setState(() {
        final diff = eventTime.difference(DateTime.now());
        if (diff.isNegative) {
          timeDiff = 0;
          print('Times up!');
          timer.cancel();
          // 添加倒计时结束后的操作
        } else {
          timeDiff = diff.inSeconds;
        }
      });
    }
  }

  @override
  void dispose() {
    timer.cancel(); // 销毁Timer,避免内存泄漏
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    // 初始化时计算初始时间差,确保数值非负
    timeDiff = eventTime.difference(DateTime.now()).inSeconds.clamp(0, double.infinity).toInt();
    // 在initState中创建Timer,确保只初始化一次
    timer = Timer.periodic(duration, (Timer t) {
      handleTick();
    });
  }

  @override
  Widget build(BuildContext context) {
    int days = timeDiff ~/ (24 * 60 * 60); // 移除多余的%24,正确计算总天数
    int hours = timeDiff ~/ (60 * 60) % 24;
    int minutes = (timeDiff ~/ 60) % 60;
    int seconds = timeDiff % 60;
    return Scaffold(
        appBar: AppBar(
          backgroundColor: const Color(0x00fafafa),
          elevation: 0,
          leading: const BackButton(color: Colors.deepOrange,),
        ),
        body: SingleChildScrollView(
          child: Column(
            children: [
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  LabelText(
                      label: 'DAYS', value: days.toString().padLeft(2, '0')),
                  LabelText(
                      label: 'HRS', value: hours.toString().padLeft(2, '0')),
                  LabelText(
                      label: 'MIN', value: minutes.toString().padLeft(2, '0')),
                  LabelText(
                      label: 'SEC', value: seconds.toString().padLeft(2, '0')),
                ],
              ),
            ],
          ),
        )
    );
  }
}


class LabelText extends StatelessWidget {
  const LabelText({super.key, required this.label, required this.value});

  final String label;
  final String value;

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.symmetric(horizontal: 5),
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(25),
        color: Colors.grey,
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text(
            value,
            style: const TextStyle(
                color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold),
          ),
          Text(
            label,
            style: const TextStyle(
              color: Colors.white70,
            ),
          ),
        ],
      ),
    );
  }
}

关键修复点

  • 天数计算:移除天数公式中的%24,直接通过总秒数除以一天的秒数得到真实剩余天数。
  • Timer生命周期管理:将Timer初始化移至initState,确保仅创建一个实例;在dispose中销毁Timer,避免内存泄漏。
  • 时间差准确性优化:每次计时触发时重新计算当前时间与目标时间的差值,避免Timer延迟导致的累计误差,同时处理倒计时结束的逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 12:35:38