class ClockComponent extends StatefulWidget {
  final String? endTime;

  ClockComponent({
    Key? key,
    this.endTime,
  }) : super(key: key);

  @override
  _ClockComponentState createState() {
    return _ClockComponentState();
  }
}

class _ClockComponentState extends State<ClockComponent> {
  // 用来在布局中显示相应的剩余时间
  String remainTime = '';
  Timer? _timer;

  @override
  void initState() {
    super.initState();
    // 初始化的时候开启倒计时
    startCountDown(widget.endTime);
  }

  @override
  void dispose() {
    super.dispose();
    // 在页面回收或滑动复用回收的时候一定要把 timer 清除
    if (_timer != null) {
      if (_timer!.isActive) {
        _timer!.cancel();
        _timer = null;
      }
    }
  }

  @override
  void didUpdateWidget(ClockComponent oldWidget) {
    super.didUpdateWidget(oldWidget);
    // 外部重新请求接口后重新进行倒计时,这个方法是用来监控外部 setState 的
    startCountDown(widget.endTime);
  }

  void startCountDown(time) {
    var nowTime = DateTime.now();
    // var endTime = DateTime.parse(time.toString());
    var endTime = DateTime.parse(time);

    // 如果剩余时间已经不足一分钟,则不必计时,直接标记超时
    if (endTime.millisecondsSinceEpoch - nowTime.millisecondsSinceEpoch <
        1000 * 60) {
      setState(() {
        remainTime = '超时';
      });
      return;
    }

    // 重新计时的时候要把之前的清除掉
    if (_timer != null) {
      if (_timer!.isActive) {
        _timer!.cancel();
        _timer = null;
      }
    }

    const repeatPeriod = const Duration(milliseconds: 1000);

    calculateTime(nowTime, endTime);

    _timer = Timer.periodic(repeatPeriod, (timer) {
      //到时回调
      nowTime = nowTime.add(repeatPeriod);

      if (endTime.millisecondsSinceEpoch - nowTime.millisecondsSinceEpoch <
          1000 * 60) {
        //取消定时器,避免无限回调
        timer.cancel();
        // timer = null;

        setState(() {
          remainTime = '超时';
        });
        return;
      }
      calculateTime(nowTime, endTime);
    });
  }

  /// 计算天数、小时、分钟、秒
  void calculateTime(nowTime, endTime) {
    var _surplus = endTime.difference(nowTime);
    int day = (_surplus.inSeconds ~/ 3600) ~/ 24;
    int hour = (_surplus.inSeconds ~/ 3600) % 24;
    int minute = _surplus.inSeconds % 3600 ~/ 60;
    int second = _surplus.inSeconds % 60;

    var str = '';
    if (day > 0) {
      str = day.toString() + '天';
    }
    if (hour > 0 || (day > 0 && hour == 0)) {
      str = str + hour.toString() + '小时';
    }
    str = str + minute.toString() + '分钟';
    str = str + second.toString() + "秒";

    setState(() {
      remainTime = str;
    });
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      child: Text("$remainTime"),
    );
  }
}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐