Stream<T>.fromIterable constructor
Null safety
- Iterable<
T> elements
Creates a stream that gets its data from elements
.
The iterable is iterated when the stream receives a listener, and stops
iterating if the listener cancels the subscription, or if the
Iterator.moveNext method returns false
or throws.
Iteration is suspended while the stream subscription is paused.
If calling Iterator.moveNext on elements.iterator
throws,
the stream emits that error and then it closes.
If reading Iterator.current on elements.iterator
throws,
the stream emits that error, but keeps iterating.
Can be listened to more than once. Each listener iterates elements
independently.
Example:
final numbers = [1, 2, 3, 5, 6, 7];
final stream = Stream.fromIterable(numbers);
Implementation
factory Stream.fromIterable(Iterable<T> elements) =>
Stream<T>.multi((controller) {
Iterator<T> iterator;
try {
iterator = elements.iterator;
} catch (e, s) {
controller.addError(e, s);
controller.close();
return;
}
var zone = Zone.current;
var isScheduled = true;
void next() {
if (!controller.hasListener || controller.isPaused) {
// Cancelled or paused since scheduled.
isScheduled = false;
return;
}
bool hasNext;
try {
hasNext = iterator.moveNext();
} catch (e, s) {
controller.addErrorSync(e, s);
controller.closeSync();
return;
}
if (hasNext) {
try {
controller.addSync(iterator.current);
} catch (e, s) {
controller.addErrorSync(e, s);
}
if (controller.hasListener && !controller.isPaused) {
zone.scheduleMicrotask(next);
} else {
isScheduled = false;
}
} else {
controller.closeSync();
}
}
controller.onResume = () {
if (!isScheduled) {
isScheduled = true;
zone.scheduleMicrotask(next);
}
};
zone.scheduleMicrotask(next);
});