Home > Back-end >  How to have timer with variable duration in Flutter
How to have timer with variable duration in Flutter

Time:05-15

How can I make a timer that its speed increases every minute i.e. the timer duration decreases evey 1 minute in Flutter?

CodePudding user response:

As say in the comments section, you can have a recursive function to do the works.

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);
    }
});

In this example, I had a minDuration limit, to avoid unwanted behavior.

You can import this code into a dart pad to try this out :)

CodePudding user response:

Here's a Timer implementation that acts like a normal periodic Timer but allows the callback to modify the period (and even the callback):

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;

Example usage that creates a periodic Timer that initially fires every 10 seconds, firing one second sooner each minute, and stopping when the period reaches 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();
      }
    }
  });
}
  • Related