Stream<T>.periodic constructor
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 = 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;
}