Last active
October 4, 2023 08:43
-
-
Save marvin-kolja/6181915ee0bc0992db83c06aa23f350c to your computer and use it in GitHub Desktop.
Custom Dart Periodic - with duration multiplier, run limit, and immediate callback execution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
/// This class allows to create a periodic timer that can run immediately | |
/// ([_runImmediately]) and can change its duration over time | |
/// ([_durationMultiplier]). | |
/// | |
/// The [_maxRuns] is the maximum number of times the timer will run. If the | |
/// timer is cancelled, it will stop running before reaching the maximum number | |
/// of runs. If the maximum number of runs is 0, the timer will run | |
/// indefinitely. | |
/// | |
/// The [_durationMultiplier] is the factor by which the duration of the timer | |
/// will be multiplied after each run. For example, if the duration is 1 second | |
/// and the multiplier is 2, the duration of the next run will be 2 seconds, | |
/// then 4, then 8, and so on. | |
/// | |
/// The [_maxDuration] is the maximum duration of the timer. If the duration | |
/// exceeds the maximum duration, the timer will stop running. If the maximum | |
/// duration is 0, the timer will run indefinitely (which is the default). | |
/// | |
/// The [_runImmediately] is a boolean that determines whether the timer will | |
/// run immediately after being created or not. | |
/// | |
class Periodic { | |
Timer? _timer; | |
bool _cancelled = false; | |
final bool _runImmediately; | |
final double _durationMultiplier; | |
final Duration _maxDuration; | |
final int _maxRuns; | |
void cancel() { | |
_cancelled = true; | |
_timer?.cancel(); | |
} | |
Periodic._internal({ | |
required bool runImmediately, | |
required double durationMultiplier, | |
required int maxRuns, | |
required Duration maxDuration, | |
}) : _runImmediately = runImmediately, | |
_durationMultiplier = durationMultiplier, | |
_maxDuration = maxDuration, | |
_maxRuns = maxRuns; | |
factory Periodic.run( | |
Duration duration, | |
Future<void> Function(Periodic) callback, { | |
bool runImmediately = false, | |
double durationMultiplier = 1.0, | |
Duration maxDuration = Duration.zero, | |
int maxRuns = 0, | |
}) { | |
if (maxRuns < 0) { | |
throw ArgumentError.value( | |
maxRuns, | |
'maxRuns', | |
'Must be greater than or equal to 0 for infinite runs.', | |
); | |
} | |
return Periodic._internal( | |
runImmediately: runImmediately, | |
durationMultiplier: durationMultiplier, | |
maxDuration: maxDuration, | |
maxRuns: maxRuns, | |
).._run(duration, callback); | |
} | |
void _run( | |
Duration duration, | |
Future<void> Function(Periodic) callback, { | |
int runCount = 1, | |
}) { | |
if (_cancelled) return; | |
if (_maxRuns > 0 && runCount > _maxRuns) return; | |
if (_maxDuration > Duration.zero && duration > _maxDuration) return; | |
if (_runImmediately && runCount == 1) callback(this); | |
_timer = Timer(duration, () async { | |
await callback(this); | |
_run(duration * _durationMultiplier, callback, runCount: runCount + 1); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Replaced old periodic with the revised version. It provides more flexibility and control over the periodic task's execution but keeps the interface clean. For instance, instead of passing
maxRuns
, you can now check the run count in the callback and cancel as you see fit.