Streams Grundlagen
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 77 von 110.
Während ein Future einen einzelnen Wert liefert, liefert ein Stream eine Sequenz von Werten über die Zeit. Stellen Sie es sich wie eine Leitung vor, die mehrere Datenstücke ausgeben kann – perfekt für Ereignisse, Echtzeit-Updates oder die schrittweise Verarbeitung von Daten.
Sie können einen einfachen Stream mit Stream.fromIterable() oder einer asynchronen Generatorfunktion mit async* und yield erstellen:
Stream<int> countToThree() async* {
yield 1;
yield 2;
yield 3;
}
Future<void> main() async {
await for (var number in countToThree()) {
print(number);
}
}
// Output: 1, 2, 3Das async*-Schlüsselwort kennzeichnet eine Funktion, die einen Stream zurückgibt, und yield gibt jeden Wert aus. Um den Stream zu konsumieren, verwenden Sie await for, das jeden Wert verarbeitet, sobald er eintrifft.
Sie können einen Stream auch mit der Methode listen() abhören, die eine Callback-Funktion entgegennimmt:
Stream<String> greetings() async* {
yield 'Hello';
yield 'Hi';
yield 'Hey';
}
void main() {
greetings().listen((message) {
print(message);
});
}Der entscheidende Unterschied zu Futures: Ein Future wird einmal mit einem einzelnen Wert abgeschlossen, während ein Stream viele Werte ausgeben kann, bevor er fertig ist. Dies macht Streams ideal für die Handhabung fortlaufender Daten wie Benutzerinteraktionen, Sensormesswerte oder Daten, die in Blöcken ankommen.
Aufgabe
EinfachLassen Sie uns ein Countdown-Timer-System bauen, das Werte über die Zeit mithilfe von Streams ausgibt! Sie werden eine Klasse erstellen, die eine Sequenz von Countdown-Zahlen generiert und demonstriert, wie Streams mehrere Werte anstatt nur eines einzelnen liefern.
Sie werden Ihren Code in zwei Dateien organisieren:
countdown.dart: Erstellen Sie eineCountdown-Klasse, die Countdown-Streams generiert. Ihre Klasse sollte Folgendes enthalten:- Ein
start-Feld (int), das die Startnummer für den Countdown speichert - Einen Konstruktor, der die Startnummer entgegennimmt
- Eine Methode
countDown(), die einenStream<int>zurückgibt. Verwenden Sieasync*undyield, um Zahlen vonstartbis hinunter zu0(einschließlich) auszugeben - Eine Methode
countDownWithMessage(), die einenStream<String>zurückgibt. Diese sollte Strings im Format'T-minus [number]'für jede Zahl vonstartbis hinunter zu1ausgeben und dann'Liftoff!'als finalen Wert senden
- Ein
main.dart: Importieren Sie Ihre Countdown-Datei und demonstrieren Sie beide Stream-Methoden. Ihre Main-Funktion sollte async sein und:- Eine
Countdown-Instanz erstellen, die bei3beginnt Number countdown:ausgebenawait forverwenden, um durchcountDown()zu iterieren und jede Zahl auszugeben- Eine Leerzeile ausgeben
Launch sequence:ausgebenawait forverwenden, um durchcountDownWithMessage()zu iterieren und jede Nachricht auszugeben
- Eine
Beachten Sie, wie jede yield-Anweisung einen Wert über den Stream ausgibt und await for jeden Wert verarbeitet, sobald er ankommt. Im Gegensatz zu einem Future, das ein einzelnes Ergebnis liefert, werden Ihre Streams mehrere Werte nacheinander ausgeben!
Erwartete Ausgabe:
Number countdown:
3
2
1
0
Launch sequence:
T-minus 3
T-minus 2
T-minus 1
Liftoff!Spickzettel
Ein Stream liefert eine Sequenz von Werten über die Zeit, im Gegensatz zu einem Future, das einen einzelnen Wert liefert. Streams sind ideal für Ereignisse, Echtzeit-Updates oder die stückweise Verarbeitung von Daten.
Erstellen Sie einen Stream mit einer asynchronen Generatorfunktion mit async* und yield:
Stream<int> countToThree() async* {
yield 1;
yield 2;
yield 3;
}Konsumieren Sie einen Stream mit await for:
Future<void> main() async {
await for (var number in countToThree()) {
print(number);
}
}Alternativ können Sie die Methode listen() mit einem Callback verwenden:
void main() {
greetings().listen((message) {
print(message);
});
}Sie können auch einen Stream aus einem Iterable mit Stream.fromIterable() erstellen.
Probier es selbst
import 'countdown.dart';
Future<void> main() async {
// TODO: Erstelle eine Countdown-Instanz, die bei 3 beginnt
// TODO: Gib 'Number countdown:' aus
// TODO: Verwende await for, um countDown() zu durchlaufen und jede Zahl auszugeben
// TODO: Gib eine Leerzeile aus
// TODO: Gib 'Launch sequence:' aus
// TODO: Verwende await for, um countDownWithMessage() zu durchlaufen und jede Nachricht auszugeben
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienBibliotheken & ImportsEinführung in die OOPKlassen vs. ObjekteDas this-SchlüsselwortMethodenInstanzvariablenKonstruktor-GrundlagenWiederholung – Einfacher Taschenrechner4Null-Sicherheit
Einführung in Null-SicherheitNullable vs. Non-NullableDie ? und ! OperatorenLate-Schlüsselwort & Null-SicherheitNull-aware OperatorenNull-Sicherheit in KlassenZusammenfassung – Benutzerprofil-System7Abstrakte Klassen & Interfaces
Abstrakte KlassenAbstrakte MethodenInterfaces in DartImplizite InterfacesImplementieren vs. ErweiternMehrfache InterfacesRückblick – Shape Calculator10Collections & Generics
Überblick über List, Set und MapTypsichere CollectionsGenerische KlassenGenerische MethodenGenerische ConstraintsIterable & IteratorZusammenfassung – Generische Speicherung13Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungExtension MethodsCallable ClassesSealed Classes (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums mit Methoden16Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen2Konstruktoren in Dart
Standard-KonstruktorBenannte KonstruktorenInitialisierungslistenKonstante KonstruktorenFactory-KonstruktorenWeiterleitende KonstruktorenZusammenfassung – Shape Builder5Kapselung
Öffentliche vs. private MemberDie _ Präfix-KonventionSichtbarkeit auf Library-EbeneGetter & Setter im DetailInformation HidingRückblick – Schülerdatensätze8Mixins
Einführung in MixinsMixins erstellenMehrere Mixins verwendenDas on-Schlüsselwort in MixinsMixin vs. VererbungMixin vs. InterfaceZusammenfassung - Tiersystem11Spezielle Methoden
toString() überschreibenhashCode & == überschreibenComparable-Interfacecall()-MethodenoSuchMethod überschreibenZusammenfassung – Eigene Collection14Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster3Klasseneigenschaften
Instanz- vs. statische MemberFinal & Const FelderLate-VariablenStatische Methoden & FelderGetter und SetterZusammenfassung – Bankkonto-Manager6Vererbung
Grundlagen der VererbungDas super-SchlüsselwortMethoden überschreibenDie @override-AnnotationDas final-Klassen-SchlüsselwortKonstruktoren & VererbungRückblick – Mitarbeiter-Hierarchie9Polymorphismus
Polymorphismus-GrundlagenPolymorphismus über InterfacesTypprüfung zur LaufzeitDie is & as OperatorenDas covariant SchlüsselwortZusammenfassung – Payment Processor12Asynchrone OOP
Futures & async/awaitStreams GrundlagenStream ControllerAsynchrone KonstruktorenAsync in KlassenmethodenZusammenfassung – Data Fetcher