How to make Timer.periodic cancel itself when a condition is reached?
19,009
Solution 1
You get the timer passed into the callback. You can just call cancel()
on it:
Timer.periodic(const Duration(seconds: 1), (timer) {
if(condition) {
timer.cancel();
}
});
or
Timer timer;
startTimer() {
timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if(condition) {
cancelTimer();
}
});
}
cancelTimer() {
timer.cancel();
}
this way the timer can be cancelled independent of a timer event.
Solution 2
You could instead use Stream.periodic
with takeWhile
bool condition = true;
Future.delayed(const Duration(seconds: 5), () => condition = false);
Stream.periodic(const Duration(seconds: 1))
.takeWhile((_) => condition)
.forEach((e) {
print('event: $e');
});
Solution 3
One solution I found is to pass a function in to the timer that returns a bool
and then use timer.cancel()
when it's satisfied. Here's a generalized way of doing this:
periodically(int milliseconds, Function repeat, [Function cancel]) {
return Timer.periodic(
Duration(milliseconds: milliseconds),
(Timer t) {
repeat();
if (cancel != null) {
cancel() ? t.cancel() : null;
}
}
);
}
Related videos on Youtube
Author by
Matt S.
Updated on June 04, 2022Comments
-
Matt S. almost 2 years
Timer.periodic()
is great to have a function repeatedly execute, but is it possible to have the the timer cancel itself if an arbitrary condition is reached outside the function being executed by the timer? -
Maritn Ge about 3 yearsIf I do option b, the Timer timer will always be null, even while the timer is running. it will run, but when i cancel it, it gives me a null exception
-
Günter Zöchbauer about 3 yearsThat's probably not related to the code in my answer. I guess cancel() is called before the timer is initialized.
-
Maritn Ge about 3 yearsYou're kinda right, I did another thing wrong, you're code works fine