Controladores de Stream
Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy. Lição 78 de 110.
Embora os geradores async* sejam ótimos para criar streams com dados predefinidos, às vezes você precisa de mais controle — como adicionar dados a um stream de diferentes partes do seu código. É aí que entra StreamController.
Um StreamController atua como um gerenciador de um fluxo. Ele fornece um "sink" para adicionar dados e um "stream" ao qual os ouvintes podem se inscrever:
import 'dart:async';
void main() {
var controller = StreamController<String>();
// Escuta o stream
controller.stream.listen((data) {
print('Received: $data');
});
// Adiciona dados através do sink
controller.add('Hello');
controller.add('World');
controller.close(); // Sempre feche quando terminar
}O método add() insere novos valores no fluxo, e todos os listeners os recebem imediatamente. Você deve sempre chamar close() quando terminar para liberar os recursos.
Por padrão, um fluxo pode ter apenas um ouvinte. Para vários ouvintes, use um controlador de transmissão:
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();
}StreamControllers são essenciais em OOP para a construção de classes orientadas a eventos - como notificar várias partes do seu aplicativo quando os dados mudam, lidar com ações do usuário ou gerenciar atualizações em tempo real dentro dos seus objetos.
Desafio
FácilVamos criar um sistema de central de mensagens que permite que vários assinantes recebam mensagens em tempo real! Você usará um StreamController para gerenciar o fluxo de mensagens e demonstrar como os streams de broadcast permitem vários ouvintes.
Você organizará seu código em dois arquivos:
message_hub.dart: crie uma classeMessageHubque gerencie a distribuição de mensagens usando um StreamController. Sua central deve:- Usar internamente um
StreamController<String>de broadcast para que vários ouvintes possam se inscrever - Fornecer um getter chamado
messagesque retorne o stream para que os ouvintes se inscrevam - Ter um método
broadcast(String message)que adicione uma mensagem ao stream - Ter um método
shutdown()que feche o controlador
- Usar internamente um
main.dart: importe sua central de mensagens e configure um cenário com vários assinantes ouvindo o mesmo stream:- Crie uma instância de
MessageHub - Adicione um primeiro ouvinte que imprima as mensagens no formato:
Subscriber A: [message] - Adicione um segundo ouvinte que imprima as mensagens no formato:
Subscriber B: [message] - Faça o broadcast de três mensagens:
Hello everyone,Welcome to the hubeGoodbye - Desligue a central
- Crie uma instância de
Lembre-se de importar dart:async no arquivo da sua central de mensagens para acessar StreamController. Observe como os dois assinantes recebem todas as mensagens que são transmitidas — esse é o poder dos streams de broadcast!
Saída esperada:
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: GoodbyeExperimente você mesmo
import 'message_hub.dart';
void main() {
// TODO: Criar uma instância de MessageHub
// TODO: Adicionar o primeiro listener que imprime: Subscriber A: [message]
// TODO: Adicionar o segundo listener que imprime: Subscriber B: [message]
// TODO: Transmitir três mensagens:
// - "Hello everyone"
// - "Welcome to the hub"
// - "Goodbye"
// TODO: Desligar o hub
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de OOP
Arquivos externosBibliotecas e importsIntrodução à OOPClasses vs. objetosA palavra-chave thisMétodosVariáveis de instânciaNoções básicas de construtoresRevisão - Calculadora simples4Segurança contra nulos
Introdução à segurança contra nulosAnulável vs. não anulávelOs operadores ? e !Palavra-chave Late e segurança contra nulosOperadores conscientes de nulosSegurança contra nulos em classesRecapitulação — Sistema de perfil de usuário7Classes Abstratas e Interfaces
Classes AbstratasMétodos AbstratosInterfaces em DartInterfaces ImplícitasImplementação vs. ExtensãoMúltiplas InterfacesRecapitulação - Calculadora de Formas10Coleções e Genéricos
Visão geral de List, Set e MapColeções com segurança de tiposClasses genéricasMétodos genéricosRestrições genéricasIterable e IteratorRecapitulação - Armazenamento genérico13Conceitos Avançados de OOP
Composição vs. HerançaMétodos de ExtensãoClasses ChamáveisClasses Seladas (Dart 3)Registros (Dart 3)Padrões e Correspondência (3.0)Enums com Métodos16Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses de Livros e Usuários2Construtores em Dart
Construtor padrãoConstrutores nomeadosListas de inicializaçãoConstrutores constantesConstrutores factoryConstrutores de redirecionamentoRevisão - Construtor de formas5Encapsulamento
Membros Públicos vs. PrivadosConvenção do Prefixo _Privacidade no Nível da BibliotecaAprofundamento em Getters e SettersOcultação de InformaçõesRecapitulação - Registros de Alunos8Mixins
Introdução a MixinsCriando MixinsUsando vários MixinsPalavra-chave on em MixinsMixin vs HerançaMixin vs InterfaceRecapitulação - Sistema de Animais11Métodos Especiais
Sobrescrita de toString()Sobrescrita de hashCode e ==Interface ComparableMétodo call()Sobrescrita de noSuchMethodRecapitulação - Coleção Personalizada14Padrões de Projeto – Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão Strategy3Propriedades de Classe
Membros de Instância vs. EstáticosCampos Final e ConstVariáveis LateMétodos e Campos EstáticosGetters e SettersRecapitulação - Gerenciador de Contas Bancárias6Herança
Herança BásicaA Palavra-chave superSobrescrita de MétodosA Anotação @overrideA Palavra-chave final para ClassesConstrutores e HerançaRecapitulação - Hierarquia de Funcionários9Polimorfismo
Fundamentos do polimorfismoPolimorfismo por meio de interfacesVerificação de tipos em tempo de execuçãoOs operadores is e asPalavra-chave covarianteRecapitulação — Processador de pagamentos12OOP Assíncrona
Futures e async/awaitNoções básicas de StreamsControladores de StreamConstrutores assíncronosAsync em métodos de classeRecapitulação — Buscador de dados15Padrões de Projeto — Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão RepositoryPratique por conta própria: Compilador de Dart online