Menu
Coddy logo textTech

Stream Controllers

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 78 de 110.

Si bien los generadores async* son excelentes para crear streams con datos predefinidos, a veces necesitas más control, como añadir datos a un stream desde diferentes partes de tu código. Ahí es donde entra en juego StreamController.

Un StreamController actúa como un gestor para un stream. Te proporciona un "sink" para añadir datos y un "stream" al que los suscriptores pueden suscribirse:

import 'dart:async';

void main() {
  var controller = StreamController<String>();
  
  // Escuchar el stream
  controller.stream.listen((data) {
    print('Received: $data');
  });
  
  // Agregar datos a través del sink
  controller.add('Hello');
  controller.add('World');
  
  controller.close();  // Cerrar siempre al terminar
}

El método add() inserta nuevos valores en el flujo, y cualquier escucha los recibe inmediatamente. Siempre debes llamar a close() cuando hayas terminado para liberar recursos.

Por defecto, un stream solo puede tener un listener. Para múltiples listeners, usa un 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();
}

Los StreamControllers son esenciales en la POO para construir clases orientadas a eventos, como notificar a múltiples partes de su aplicación cuando los datos cambian, manejar acciones del usuario o gestionar actualizaciones en tiempo real dentro de sus objetos.

challenge icon

Desafío

Fácil

¡Vamos a construir un sistema de centro de mensajes que permita a múltiples suscriptores recibir mensajes en tiempo real! Utilizarás un StreamController para gestionar el flujo de mensajes y demostrar cómo los flujos de difusión (broadcast streams) permiten múltiples oyentes.

Organizarás tu código en dos archivos:

  • message_hub.dart: Crea una clase MessageHub que gestione la distribución de mensajes utilizando un StreamController. Tu centro debe:
    • Usar un StreamController<String> de tipo broadcast internamente para que múltiples oyentes puedan suscribirse
    • Proporcionar un getter llamado messages que devuelva el flujo para que los oyentes se suscriban
    • Tener un método broadcast(String message) que añada un mensaje al flujo
    • Tener un método shutdown() que cierre el controlador
  • main.dart: Importa tu centro de mensajes y configura un escenario con múltiples suscriptores escuchando el mismo flujo:
    • Crea una instancia de MessageHub
    • Añade un primer oyente que imprima los mensajes en el formato: Subscriber A: [message]
    • Añade un segundo oyente que imprima los mensajes en el formato: Subscriber B: [message]
    • Transmite tres mensajes: Hello everyone, Welcome to the hub, y Goodbye
    • Cierra el centro de mensajes

Recuerda importar dart:async en tu archivo del centro de mensajes para acceder a StreamController. Observa cómo ambos suscriptores reciben cada mensaje que se transmite: ¡ese es el poder de los flujos de difusión!

Salida 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

Pruébalo tú mismo

import 'message_hub.dart';

void main() {
  // TODO: Crea una instancia de MessageHub
  
  // TODO: Añade el primer listener que imprima: Subscriber A: [message]
  
  // TODO: Añade el segundo listener que imprima: Subscriber B: [message]
  
  // TODO: Transmite tres mensajes:
  // - "Hello everyone"
  // - "Welcome to the hub"
  // - "Goodbye"
  
  // TODO: Cierra el hub
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos