Ce face StreamTransformer
Un StreamTransformer<S, T> primește un stream și dă alt stream, prin metoda bind; de obicei îl folosești prin stream.transform(t). Spre deosebire de map, poate emite mai multe valori pentru una, niciuna, sau poate păstra o stare între valori.
StreamTransformer.fromHandlers este cel mai simplu mod de a crea unul: handleData primește fiecare valoare și un sink în care scrii rezultatele, handleError primește erorile, iar handleDone rulează la final (poți scrie ultimele valori înainte de sink.close()). Funcțiile care lipsesc trimit evenimentele mai departe neschimbate.
Parametri
| Parametru | Descriere |
|---|---|
handleData |
Ce faci cu fiecare valoare; rezultatele se scriu în sink. |
handleError |
Opțional: ce faci cu fiecare eroare. |
handleDone |
Opțional: ce faci la final; trebuie să chemi sink.close(). |
Ce returnează
Un transformator care se aplică cu stream.transform(...).
Exemple
Exemplul 1: Grupare câte 2
Transformatorul păstrează o stare (lista curentă) și la final trimite ce a rămas.
import 'dart:async';
StreamTransformer<String, List<String>> grupe(int marime) {
var curent = <String>[];
return StreamTransformer.fromHandlers(
handleData: (x, sink) {
curent.add(x);
if (curent.length == marime) {
sink.add(curent);
curent = [];
}
},
handleDone: (sink) {
if (curent.isNotEmpty) sink.add(curent);
sink.close();
},
);
}
Future<void> main() async {
final elevi = Stream.fromIterable(['Ana', 'Mihai', 'Ioana', 'Radu', 'Elena']);
await elevi.transform(grupe(2)).forEach((g) => print('Bancă: $g'));
}
Rezultat
Bancă: [Ana, Mihai]
Bancă: [Ioana, Radu]
Bancă: [Elena]
Exemplul 2: Erorile transformate în valori
import 'dart:async';
final sigur = StreamTransformer<int, String>.fromHandlers(
handleData: (n, sink) => sink.add('ok: $n'),
handleError: (e, st, sink) => sink.add('eroare înlocuită: $e'),
);
Future<void> main() async {
final s = Stream<int>.multi((c) {
c.add(1);
c.addError(StateError('citire eșuată'));
c.add(3);
c.close();
});
print(await s.transform(sigur).toList());
}
Rezultat
[ok: 1, eroare înlocuită: Bad state: citire eșuată, ok: 3]
Greșeli frecvente
- Scrii
handleDoneși uițisink.close(). Stream-ul rezultat nu se mai închide. - Ții starea într-o variabilă globală. Dacă folosești același transformator pe două stream-uri, starea se amestecă; creează-l printr-o funcție, ca în exemplu.
Comenzi înrudite
Stream.transform: Trece stream-ul printr-un StreamTransformer, de exemplu utf8.decoder sau LineSplitter, și dă stream-ul rezultat.StreamTransformer.fromBind: Creează un transformator dintr-o funcție care primește tot stream-ul și returnează stream-ul nou.StreamSink: Interfața „capătului de scriere” al unui stream: add, addError, addStream, close și done.LineSplitter: Împarte un text în rânduri, recunoscând \n, \r\n și \r; funcționează și pe fluxuri cu transform.