Ce face Stream
Dacă un Future este o singură valoare care vine mai târziu, un Stream<T> este o succesiune de valori care vin pe rând, urmate eventual de un semnal de final („done”). Pe lângă valori, un stream poate emite și erori.
Cel mai simplu îl parcurgi cu await for, într-o funcție async: bucla primește fiecare valoare când sosește și se termină când stream-ul se închide. Poți crea un stream cu o funcție async* care face yield, cu constructori ca Stream.fromIterable sau cu un StreamController.
Stream-urile obișnuite („single-subscription”) pot fi ascultate o singură dată. Ca la Iterable, ai map, where, take și altele, care returnează stream-uri noi, plus metode ca toList sau first, care returnează un Future.
Ce returnează
Un obiect Stream<T>; valorile lui se primesc prin await for sau listen.
Exemple
Exemplul 1: Un stream creat cu async* și citit cu await for
Stream<int> numaratoare(int de) async* {
for (var i = de; i > 0; i--) {
await Future.delayed(const Duration(milliseconds: 50));
yield i;
}
}
Future<void> main() async {
await for (final n in numaratoare(3)) {
print('$n...');
}
print('Lansare!');
}
Rezultat
3...
2...
1...
Lansare!
Exemplul 2: Transformări în lanț
Future<void> main() async {
final temperaturi = Stream.fromIterable([18, 25, 31, 22, 34, 29]);
final caniculare = temperaturi.where((t) => t >= 30).map((t) => '$t °C');
print(await caniculare.toList());
}
Rezultat
[31 °C, 34 °C]
Exemplul 3: Un stream obișnuit se ascultă o singură dată
Future<void> main() async {
final s = Stream.fromIterable(['Ana', 'Mihai']);
print(await s.toList());
try {
await s.toList();
} on StateError catch (e) {
print('A doua ascultare: ${e.message}');
}
}
Rezultat
[Ana, Mihai]
Greșeli frecvente
- Asculți de două ori același stream obișnuit. Apare
StateError: Stream has already been listened to; folosește un stream broadcast sauasBroadcastStream. - Folosești
await forpe un stream care nu se închide niciodată (de exempluStream.periodic). Bucla nu se termină; limitează-l cutake.
Comenzi înrudite
Stream.listen: Începe ascultarea unui stream: o funcție pentru fiecare valoare, una pentru erori, una pentru final.await for: Parcurge un Stream element cu element, așteptând fiecare eveniment; se termină când stream-ul se închide.async*: O funcție async* produce un Stream: trimite valori cu yield, în timp, și poate folosi await între ele.StreamController: Creează un stream pe care îl alimentezi tu: ce pui cu add ajunge la cei care ascultă controller.stream.Future: O valoare care va fi gata mai târziu (citirea unui fișier, un răspuns de la server); o aștepți cu await.Stream.fromIterable: Creează un stream care emite, pe rând, elementele unei liste sau ale altui Iterable, apoi se închide.