如何在Flutter中设置持续时间可变的计时器

z2acfund  于 2023-02-16  发布在  Flutter
关注(0)|答案(3)|浏览(174)

我怎样才能使计时器的速度每分钟增加一次,即在Flutter中计时器的持续时间每1分钟减少一次?

oug3syen

oug3syen1#

正如在注解部分所说的,您可以使用递归函数来完成这些工作。

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中进行尝试:)

oxf4rvwz

oxf4rvwz2#

下面是一个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的示例用法,该周期性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();
      }
    }
  });
}
bmvo0sr5

bmvo0sr53#

您可以只创建一个具有最小周期的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++;
  });
}

上面的代码创建了一个显式的tTick计数器,但是Timer对象有一个示例变量timer.tick,它非常适合于实现同样的目的。

相关问题