En Dart, un Stream es una secuencia asincrónica de datos que se pueden procesar a medida que están disponibles. A diferencia de un Future
, que produce un único valor en el futuro, un Stream
permite recibir múltiples valores a lo largo del tiempo, como eventos o actualizaciones en tiempo real, por ejemplo, datos de sensores, cambios de estado en la interfaz, o información recibida desde una conexión de red.
Un Stream
es una clase que permite manejar una secuencia de datos asincrónicos que llegan uno tras otro. Los Streams
pueden ser de dos tipos:
1. Stream de un solo suscriptor: Permite un solo receptor a la vez.
2. Stream de difusión (broadcast): Permite múltiples suscriptores simultáneamente.
Para crear un Stream
, usa StreamController
, que permite gestionar la entrada y salida de datos de un Stream
. A continuación, se muestra un ejemplo básico:
import 'dart:async';
void main() {
final controlador = StreamController<int>();
// Suscripción al Stream
controlador.stream.listen((dato) {
print('Dato recibido: $dato');
});
// Agregar datos al Stream
controlador.sink.add(1);
controlador.sink.add(2);
controlador.sink.add(3);
// Cerrar el controlador
controlador.close();
}
En este ejemplo, cada vez que se añade un dato al Stream
, el suscriptor recibe el valor y lo imprime.
Puedes usar el método listen
para suscribirte a un Stream
y recibir cada dato:
import 'dart:async';
void main() {
Stream<int> streamNumeros = Stream.fromIterable([10, 20, 30, 40]);
streamNumeros.listen((numero) {
print('Número recibido: $numero');
});
}
Este ejemplo crea un Stream
a partir de una lista de números y luego los imprime conforme se reciben.
Un Stream
de tipo broadcast
permite múltiples suscriptores, lo cual es útil cuando necesitas que varias partes de tu código reciban los mismos datos.
import 'dart:async';
void main() {
final controlador = StreamController<int>.broadcast();
controlador.stream.listen((dato) => print("Suscriptor 1: $dato"));
controlador.stream.listen((dato) => print("Suscriptor 2: $dato"));
controlador.sink.add(1);
controlador.sink.add(2);
controlador.close();
}
En este caso, ambos suscriptores reciben los datos emitidos por el Stream
de difusión.
Puedes manejar errores en un Stream
usando el parámetro onError
en listen
.
import 'dart:async';
void main() {
final controlador = StreamController<int>();
controlador.stream.listen(
(dato) => print('Dato recibido: $dato'),
onError: (error) => print('Error: $error'),
);
controlador.sink.add(1);
controlador.sink.addError('Ocurrió un error');
controlador.close();
}
Puedes modificar o filtrar datos en un Stream
usando métodos como map
y where
.
import 'dart:async';
void main() {
Stream<int> numeros = Stream.fromIterable([1, 2, 3, 4, 5]);
numeros.where((n) => n.isEven).map((n) => n * 2).listen((n) {
print('Número procesado: $n');
});
}
En este ejemplo, solo los números pares son seleccionados y luego se multiplican por 2 antes de ser impresos.
Si tienes un Stream
de un solo suscriptor y necesitas que permita múltiples suscriptores, puedes utilizar asBroadcastStream
.
import 'dart:async';
void main() {
Stream<int> streamUnico = Stream.fromIterable([1, 2, 3, 4]).asBroadcastStream();
streamUnico.listen((dato) => print('Suscriptor 1: $dato'));
streamUnico.listen((dato) => print('Suscriptor 2: $dato'));
}
Para más detalles, consulta la documentación oficial de Dart sobre Stream.
Jorge García
Fullstack developer