Stream<T>.periodic 构造函数

Stream<T>.periodic(
  1. Duration period,
  2. [T computation(
    1. int computationCount
    )?]
)

创建一个在指定间隔 period 中重复发出事件的流。

事件值通过调用 computation 计算得出。此回调的参数是一个整数,从0开始,并且每次事件都会递增。

period 必须是非负的 Duration

如果省略 computation,则事件值将全部为 null

如果事件类型 T 不允许以 null 作为值,则不得省略 computation

示例

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.

实现

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 = new Stopwatch();
  controller.onListen = () {
    int computationCount = 0;
    void sendEvent(_) {
      watch.reset();
      if (computation != null) {
        T event;
        try {
          event = computation(computationCount++);
        } catch (e, s) {
          controller.addError(e, s);
          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 = new Timer(period - elapsed, () {
          timer = Timer.periodic(period, sendEvent);
          sendEvent(null);
        });
      };
  };
  return controller.stream;
}