Controller degli stream
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 78 di 110.
Sebbene i generatori async* siano ottimi per creare flussi con dati predefiniti, a volte hai bisogno di più controllo, ad esempio per aggiungere dati a un flusso da diverse parti del tuo codice. È qui che entra in gioco StreamController.
Un StreamController funge da gestore per uno stream. Ti fornisce un "sink" a cui aggiungere dati e uno "stream" a cui gli ascoltatori possono iscriversi:
import 'dart:async';
void main() {
var controller = StreamController<String>();
// Ascolta il flusso
controller.stream.listen((data) {
print('Received: $data');
});
// Aggiungi dati tramite il sink
controller.add('Hello');
controller.add('World');
controller.close(); // Chiudi sempre quando hai finito
}Il metodo add() inserisce nuovi valori nello stream e tutti i listener li ricevono immediatamente. Dovresti sempre chiamare close() quando hai finito, per liberare le risorse.
Per impostazione predefinita, uno stream può avere un solo ascoltatore. Per più ascoltatori, usa un controller broadcast:
import 'dart:async';
void main() {
var controller = StreamController<int>.broadcast();
controller.stream.listen((n) => print('Listener 1: $n'));
controller.stream.listen((n) => print('Listener 2: $n'));
controller.add(42);
controller.close();
}Gli StreamController sono essenziali nella OOP per creare classi basate sugli eventi, ad esempio per notificare più parti della tua app quando i dati cambiano, gestire le azioni degli utenti o amministrare aggiornamenti in tempo reale all'interno dei tuoi oggetti.
Sfida
FacileCreiamo un sistema di hub di messaggi che consenta a più sottoscrittori di ricevere messaggi in tempo reale! Userai un StreamController per gestire il flusso dei messaggi e mostrare come gli stream broadcast consentano a più listener di ascoltare.
Organizzerai il codice in due file:
message_hub.dart: crea una classeMessageHubche gestisca la distribuzione dei messaggi usando uno StreamController. Il tuo hub dovrebbe:- Usare internamente un
StreamController<String>broadcast, in modo che più listener possano sottoscriversi - Fornire un getter chiamato
messagesche restituisca lo stream a cui i listener possono sottoscriversi - Avere un metodo
broadcast(String message)che aggiunga un messaggio allo stream - Avere un metodo
shutdown()che chiuda il controller
- Usare internamente un
main.dart: importa il tuo hub di messaggi e imposta uno scenario con più sottoscrittori in ascolto sullo stesso stream:- Crea un'istanza di
MessageHub - Aggiungi un primo listener che stampi i messaggi nel formato:
Subscriber A: [message] - Aggiungi un secondo listener che stampi i messaggi nel formato:
Subscriber B: [message] - Trasmetti tre messaggi:
Hello everyone,Welcome to the hubeGoodbye - Arresta l'hub
- Crea un'istanza di
Ricorda di importare dart:async nel file dell'hub di messaggi per accedere a StreamController. Nota come entrambi i sottoscrittori ricevano ogni messaggio trasmesso: questa è la potenza degli stream broadcast!
Output previsto:
Subscriber A: Hello everyone
Subscriber B: Hello everyone
Subscriber A: Welcome to the hub
Subscriber B: Welcome to the hub
Subscriber A: Goodbye
Subscriber B: GoodbyeProvalo tu
import 'message_hub.dart';
void main() {
// TODO: Crea un'istanza di MessageHub
// TODO: Aggiungi il primo listener che stampa: Subscriber A: [message]
// TODO: Aggiungi il secondo listener che stampa: Subscriber B: [message]
// TODO: Trasmetti tre messaggi:
// - "Hello everyone"
// - "Welcome to the hub"
// - "Goodbye"
// TODO: Chiudi l'hub
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniLibrerie e importazioniIntroduzione alla programmazione orientata agli oggettiClassi e oggettiLa parola chiave thisMetodiVariabili di istanzaFondamenti dei costruttoriRiepilogo - Calcolatrice semplice4Sicurezza dei valori null
Introduzione alla sicurezza dei valori nullNullable e non nullableGli operatori ? e !La keyword late e la sicurezza dei valori nullOperatori null-awareSicurezza dei valori null nelle classiRiepilogo - Sistema di profili utente7Classi astratte e interfacce
Classi astratteMetodi astrattiInterfacce in DartInterfacce impliciteImplementare vs estendereInterfacce multipleRiepilogo - Calcolatore di forme10Collezioni e generici
Panoramica di List, Set e MapCollezioni sicure rispetto ai tipiClassi genericheMetodi genericiVincoli sui genericiIterable e IteratorRiepilogo - Archiviazione generica13Concetti avanzati di OOP
Composizione vs ereditarietàMetodi di estensioneClassi chiamabiliClassi sealed (Dart 3)Record (Dart 3)Pattern e matching (3.0)Enum con metodi16Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e Utente2I costruttori in Dart
Costruttore predefinitoCostruttori con nomeListe di inizializzazioneCostruttori costantiCostruttori factoryCostruttori di reindirizzamentoRiepilogo - Crea forme5Incapsulamento
Membri pubblici e privatiConvenzione del prefisso _Visibilità a livello di libreriaApprofondimento su getter e setterNascondimento delle informazioniRiepilogo - Registri degli studenti8Mixin
Introduzione ai MixinCreare MixinUsare più MixinParola chiave on nei MixinMixin vs ereditarietàMixin vs interfacciaRiepilogo - Sistema animale11Metodi speciali
Sovrascrittura di toString()Sovrascrittura di hashCode e ==Interfaccia ComparableMetodo call()Sovrascrittura di noSuchMethodRiepilogo - Collezione personalizzata14Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneSingletonFactoryObserverStrategy3Proprietà delle classi
Membri di istanza e staticiCampi final e constVariabili lateMetodi e campi staticiGetter e setterRiepilogo - Gestore di conti bancari6Ereditarietà
Ereditarietà di baseLa parola chiave superOverride dei metodiL’annotazione @overrideLa parola chiave final per le classiCostruttori ed ereditarietàRiepilogo - Gerarchia dei dipendenti9Polimorfismo
Fondamenti di polimorfismoPolimorfismo tramite interfacceControllo del tipo a runtimeGli operatori is e asParola chiave covariantRiepilogo - Elaboratore di pagamenti12OOP asincrona
Future e async/awaitNozioni di base sugli streamController degli streamCostruttori asincroniAsync nei metodi di classeRiepilogo - Recupero dei dati15Pattern di progettazione Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern RepositoryEsercitati da solo: Compilatore Dart online