repeat static method

PostFrameRepeater repeat(
  1. FutureOr<void> action(
    1. int iteration
    ), {
  2. int? maxIterations,
  3. Duration? interval,
  4. bool waitForEndOfFrame = false,
})

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