În timp ce un Future<T> reprezintă o singură valoare care va deveni disponibilă în viitor, un Stream<T> modelează o secvență asincronă de date sau evenimente emise în timp (rețea, evenimente UI, date din socket-uri sau senzori hardware).
Pentru a produce stream-uri într-un mod declarativ și lizibil, Dart oferă generatoarele asincrone, definite prin sintaxa async* și cuvintele cheie yield (pentru a emite o valoare unică) și yield* (pentru a delega emiterea către un alt stream sau iterable complet).
Generator Asincron cu async* și yield*
import 'dart:async';
// Generator asincron care emite evenimente temporizate:
Stream countdown(int from) async* {
for (int i = from; i >= 0; i--) {
await Future.delayed(const Duration(milliseconds: 200));
yield i; // Emite valoarea curentă în stream
}
}
// Delegare către un alt stream folosind yield*:
Stream combinedStream() async* {
yield 'Start cronometru:';
// yield* consumă stream-ul 'countdown' și îi retransmite toate valorile:
yield* countdown(3).map((num) => 'T-minus: $num');
yield 'Lansare reușită!';
}
Future main() async {
await for (final message in combinedStream()) {
print(message);
}
}
Tipuri Fundamentale de Stream-uri în Dart
| Tip de Stream | Număr Maxim de Abonamente | Comportament dacă nu există abonat | Cazuri Tipice de Utilizare |
|---|---|---|---|
| Single-Subscription Stream | Exact 1 abonat | Pune datele în buffer până când ascultătorul se abonează. | Descărcare fișiere, citire din fișiere I/O, răspunsuri HTTP. |
| Broadcast Stream | Multipli abonați simultan | Evenimentele sunt emise instant; dacă nu există ascultător, se pierd. | Evenimente de click UI, actualizări GPS, WebSocket mesagerie live. |
Crearea unui StreamTransformer Personalizat
import 'dart:async';
// Transformator care filtrează datele goale și le convertește în majuscule:
final sanitizeTransformer = StreamTransformer.fromHandlers(
handleData: (data, EventSink sink) {
final trimmed = data.trim();
if (trimmed.isNotEmpty) {
sink.add(trimmed.toUpperCase());
}
},
handleError: (error, stackTrace, sink) {
sink.add('EROARE INTERCEPTATĂ: $error');
},
);
void main() {
final inputController = StreamController();
inputController.stream
.transform(sanitizeTransformer)
.listen((cleanData) => print('Output: $cleanData'));
inputController.add(' salutare ');
inputController.add(' '); // Ignorat de transformator
inputController.add('dart reactive programming');
}