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