【问题标题】:How to have timer with variable duration in Flutter如何在 Flutter 中使用可变持续时间的计时器
【发布时间】:2023-02-14 03:58:34
【问题描述】:

如何制作一个计时器,使其速度每分钟增加一次,即计时器持续时间在 Flutter 中每 1 分钟减少一次?

【问题讨论】:

  • 使用Timer构造函数(每次减少duration),而不是Timer.periodic
  • 你能详细说明一下吗?也许是一个例子!
  • 你用 60 秒 duration 调用 Timer,当 callback 完成时你用 58 秒再次调用它,然后用 56 等

标签: flutter dart


【解决方案1】:

如 cmets 部分所述,您可以使用递归函数来完成这些工作。

import 'dart:async';

void main() {
  launchTimer(Duration(seconds: 2), minDuration: Duration(milliseconds: 300));
}

void launchTimer(Duration duration, {Duration? minDuration}) =>   Timer(duration, () {
    final wantedDuration = duration - Duration(milliseconds: 300);
  
    if (minDuration != null && wantedDuration < minDuration) {
      print('minDuration');
      launchTimer(minDuration, minDuration: minDuration);
    } else {
      print('wantedDuration');
      launchTimer(wantedDuration, minDuration: minDuration);
    }
});

在这个例子中,我有一个 minDuration 限制,以避免不必要的行为。

您可以将此代码导入 dart pad 中进行尝试 :)

【讨论】:

  • 谢谢。我相信这样就可以了。所以在这种情况下,如果我想在条件成立时停止计时器,那么我就不再调用 launchTimer 函数,对吗?我不需要在这里使用任何 timer.cancel() 因为计时器不是周期性的。
  • 再补充一点,为什么限制是300毫秒。如果我没记错的话,我想我在其他地方看到过这个数字。我们不能使用更小的持续时间值吗?我希望这个计时器通过 setState 更新有状态的小部件。所以你认为我不应该设置小于 300 毫秒的值?这一切的主要原因是因为我想使用比 300 毫秒更小的持续时间值!
  • 你可以设置任何你想要的持续时间,这只是一个例子:)
【解决方案2】:

这是一个 Timer 实现,它的行为类似于普通的周期性 Timer 但允许回调修改周期(​​甚至回调):

import 'dart:async';

class VariableTimer implements Timer {
  void Function(VariableTimer) callback;
  Duration period;
  Timer? _timer;
  int _tick = 0;

  VariableTimer(Duration initialPeriod, this.callback)
      : period = initialPeriod {
    _timer = Timer(initialPeriod, _onTimer);
  }

  @override
  bool get isActive => _timer != null;

  @override
  int get tick => _tick;

  @override
  void cancel() {
    _timer?.cancel();
    _timer = null;
  }

  void _onTimer() {
    var stopwatch = Stopwatch()..start();
    _tick += 1;
    callback(this);
    if (!isActive) {
      return;
    }

    var adjustedPeriod = _max(Duration.zero, period - stopwatch.elapsed);
    _timer = Timer(adjustedPeriod, _onTimer);
  }
}

Duration _max(Duration duration1, Duration duration2) =>
    duration1 >= duration2 ? duration1 : duration2;

创建周期性 Timer 的示例用法,最初每 10 秒触发一次,每分钟提前一秒触发,并在周期达到 0 时停止:

void main() {
  const oneMinute = Duration(minutes: 1);
  var nextUpdate = DateTime.now().add(oneMinute);
  VariableTimer(const Duration(seconds: 10), (timer) {
    print(DateTime.now());
    
    var timeToNext = nextUpdate.difference(DateTime.now());
    if (timeToNext <= Duration.zero) {
      nextUpdate = nextUpdate.add(oneMinute);

      timer.period -= const Duration(seconds: 1);
      if (timer.period <= Duration.zero) {
        timer.cancel();
      }
    }
  });
}

【讨论】:

    【解决方案3】:

    你可以只用你的最小周期创建一个Timer.periodic,并在回调中使用静态计数器来标记该可变周期的倍数。这样做的好处是可以很容易地扩展到在不同时期运行的任意数量的任务——所有任务都由同一个计时器驱动。

    import 'dart:async';
    import 'dart:math';
    
    const int minPeriod=1;
    const int maxPeriod=10;
    const double decreaseRate=0.1;
    
    int variablePeriodSeconds(int t) {
      var p=decreaseRate*t;
      return max(maxPeriod-p.floor(),minPeriod); // simple linear decrease
    }
    
    void main() {
      int tTick=0;
      int tTock=0;
      final Duration minDuration = Duration(seconds: minPeriod);
      Timer timer = Timer.periodic(minDuration, (Timer timer) {
      print('tick');
      if(tTick-tTock >= variablePeriodSeconds(tTick)){
          print("TOCK!");
          tTock=tTick;
      }
      tTick++;
      });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-26
      • 1970-01-01
      • 2016-01-18
      • 2013-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多