Menu
Coddy logo textTech

Stream Controllers

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 uma stream de diferentes partes do seu código. É aí que o StreamController entra.

Um StreamController atua como um gerenciador para uma stream. Ele fornece um "sink" para adicionar dados e uma "stream" na 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 stream, e quaisquer ouvintes os recebem imediatamente. Você deve sempre chamar close() quando terminar para liberar recursos.

Por padrão, uma stream pode ter apenas um listener. Para múltiplos listeners, use um broadcast controller:

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.

challenge icon

Desafio

Fácil

Vamos construir um sistema de hub de mensagens que permite que múltiplos assinantes recebam mensagens em tempo real! Você usará um StreamController para gerenciar o fluxo de mensagens e demonstrar como as streams de transmissão (broadcast) permitem múltiplos ouvintes.

Você organizará seu código em dois arquivos:

  • message_hub.dart: Crie uma classe MessageHub que gerencia a distribuição de mensagens usando um StreamController. Seu hub deve:
    • Usar um StreamController<String> de broadcast internamente para que múltiplos ouvintes possam se inscrever
    • Fornecer um getter chamado messages que retorna a stream para os ouvintes se inscreverem
    • Ter um método broadcast(String message) que adiciona uma mensagem à stream
    • Ter um método shutdown() que fecha o controller
  • main.dart: Importe seu hub de mensagens e configure um cenário com múltiplos assinantes ouvindo a mesma stream:
    • Crie uma instância de MessageHub
    • Adicione um primeiro ouvinte que imprime mensagens no formato: Subscriber A: [message]
    • Adicione um segundo ouvinte que imprime mensagens no formato: Subscriber B: [message]
    • Transmita (broadcast) três mensagens: Hello everyone, Welcome to the hub, e Goodbye
    • Desligue o hub

Lembre-se de importar dart:async no seu arquivo do hub de mensagens para acessar o StreamController. Observe como ambos os assinantes recebem cada mensagem que é transmitida - esse é o poder das 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: Goodbye

Folha de consulta

Um StreamController gerencia uma stream, fornecendo controle sobre quando e como os dados são adicionados. Ele fornece um "sink" para adicionar dados e uma "stream" na qual os ouvintes podem se inscrever.

Uso básico:

import 'dart:async';

var controller = StreamController<String>();

// Escuta a 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() envia novos valores para a stream. Os ouvintes os recebem imediatamente. Sempre chame close() ao terminar para liberar recursos.

Por padrão, uma stream pode ter apenas um ouvinte. Para múltiplos ouvintes, use um controlador de broadcast:

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 para construir classes orientadas a eventos, 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.

Experimente 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
}
quiz iconTeste seus conhecimentos

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