repeat static method
Repeatedly schedules action to run on subsequent frames (optionally
waiting for endOfFrame) until maxIterations is reached or canceled.
The action receives the current 0-based iteration index.
If interval is provided a timer delay is inserted between iterations
(after the previous frame completes) allowing throttling.
Implementation
static PostFrameRepeater repeat(
FutureOr<void> Function(int iteration) action, {
int? maxIterations,
Duration? interval,
bool waitForEndOfFrame = false,
}) {
final binding = WidgetsBinding.instance;
final repeater = PostFrameRepeater._(maxIterations: maxIterations);
void scheduleNextFrame() => binding.scheduleFrame();
void runIteration() async {
if (repeater._canceled) return;
if (repeater.maxIterations != null &&
repeater.iterations >= repeater.maxIterations!) {
repeater._complete();
return;
}
try {
if (waitForEndOfFrame) {
await binding.endOfFrame;
}
final i = repeater.iterations;
repeater.iterations++;
await Future.sync(() => action(i));
repeater._notifyIteration();
} catch (e, st) {
repeater._error = e;
repeater._stackTrace = st;
repeater.cancel();
return;
}
if (!repeater._canceled) {
if (repeater.maxIterations != null &&
repeater.iterations >= repeater.maxIterations!) {
repeater._complete();
return;
}
if (interval != null) {
Timer(interval, () {
scheduleNextFrame();
binding.addPostFrameCallback((_) => runIteration());
});
} else {
scheduleNextFrame();
binding.addPostFrameCallback((_) => runIteration());
}
}
}
// Schedule first iteration after current frame.
binding.addPostFrameCallback((_) => runIteration());
scheduleNextFrame();
return repeater;
}