description

# Stream<T>.periodic constructor

Stream<T>.periodic(

1. Duration period, [
2. T computation(
   1. int computationCount
   )?

])

Creates a stream that repeatedly emits events at `period` intervals.

The event values are computed by invoking `computation`. The argument to this callback is an integer that starts with 0 and is incremented for every event.

The `period` must be a non-negative Duration.

If `computation` is omitted, the event values will all be `null`.

The `computation` must not be omitted if the event type `T` does not allow `null` as a value.

Example:

    final stream =
        Stream<int>.periodic(const Duration(
            seconds: 1), (count) => count * count).take(5);

    stream.forEach(print); // Outputs event values 0,1,4,9,16.

## Implementation

    factory Stream.periodic(
      Duration period, [
      T computation(int computationCount)?,
    ]) {
      if (computation == null && !typeAcceptsNull<T>()) {
        throw ArgumentError.value(
          null,
          "computation",
          "Must not be omitted when the event type is non-nullable",
        );
      }
      var controller = _SyncStreamController<T>(null, null, null, null);
      // Counts the time that the Stream was running (and not paused).
      Stopwatch watch = Stopwatch();
      controller.onListen = () {
        int computationCount = 0;
        void sendEvent(_) {
          watch.reset();
          if (computation != null) {
            T event;
            try {
              event = computation(computationCount++);
            } catch (e, s) {
              var error = _interceptCaughtError(e, s);
              controller.addError(error.error, error.stackTrace);
              return;
            }
            controller.add(event);
          } else {
            controller.add(null as T); // We have checked that null is T.
          }
        }

        Timer timer = Timer.periodic(period, sendEvent);
        controller
          ..onCancel = () {
            timer.cancel();
            return Future._nullFuture;
          }
          ..onPause = () {
            watch.stop();
            timer.cancel();
          }
          ..onResume = () {
            Duration elapsed = watch.elapsed;
            watch.start();
            timer = Timer(period - elapsed, () {
              timer = Timer.periodic(period, sendEvent);
              sendEvent(null);
            });
          };
      };
      return controller.stream;
    }