Els streams són una característica poderosa de Dart que permet treballar amb seqüències d'esdeveniments asíncrons. Són especialment útils per gestionar fluxos de dades que arriben de manera contínua, com ara dades de xarxa, esdeveniments d'usuari o fitxers.

Conceptes Clau

Què és un Stream?

Un stream és una seqüència d'esdeveniments asíncrons. Cada esdeveniment pot ser un valor, un error o una notificació de finalització. Els streams són similars a les futures, però en lloc de representar un únic valor asíncron, representen una seqüència de valors.

Tipus de Streams

Hi ha dos tipus principals de streams en Dart:

  1. Single-subscription streams: Aquests streams permeten un únic oient. Són útils per a seqüències d'esdeveniments que només necessiten ser escoltades una vegada.
  2. Broadcast streams: Aquests streams permeten múltiples oients. Són útils per a esdeveniments que poden ser escoltats per diversos oients simultàniament.

Creació de Streams

Single-subscription Stream

import 'dart:async';

void main() {
  // Creació d'un single-subscription stream
  Stream<int> stream = Stream<int>.periodic(Duration(seconds: 1), (count) => count).take(5);

  // Escoltar el stream
  stream.listen((data) {
    print('Data: $data');
  });
}

Explicació:

  • Stream<int>.periodic: Crea un stream que emet un valor cada segon.
  • take(5): Limita el stream a 5 esdeveniments.
  • listen: Escolta els esdeveniments del stream.

Broadcast Stream

import 'dart:async';

void main() {
  // Creació d'un broadcast stream
  StreamController<int> controller = StreamController<int>.broadcast();

  // Escoltar el stream
  controller.stream.listen((data) {
    print('Listener 1: $data');
  });

  controller.stream.listen((data) {
    print('Listener 2: $data');
  });

  // Emissió d'esdeveniments
  for (int i = 0; i < 5; i++) {
    controller.add(i);
  }

  // Tancar el controlador
  controller.close();
}

Explicació:

  • StreamController<int>.broadcast(): Crea un controlador de stream de tipus broadcast.
  • controller.stream.listen: Afegeix múltiples oients al stream.
  • controller.add: Emissió d'esdeveniments al stream.
  • controller.close(): Tanca el controlador del stream.

Manipulació de Streams

Transformació de Streams

Els streams poden ser transformats utilitzant diverses operacions com map, where, expand, etc.

import 'dart:async';

void main() {
  Stream<int> stream = Stream<int>.periodic(Duration(seconds: 1), (count) => count).take(5);

  // Transformació del stream
  Stream<String> transformedStream = stream.map((data) => 'Value: $data');

  transformedStream.listen((data) {
    print(data);
  });
}

Explicació:

  • map: Transforma cada esdeveniment del stream original en un nou valor.

Gestió d'Errors

Els streams poden gestionar errors utilitzant el paràmetre onError en el mètode listen.

import 'dart:async';

void main() {
  Stream<int> stream = Stream<int>.periodic(Duration(seconds: 1), (count) {
    if (count == 3) {
      throw Exception('Error al valor 3');
    }
    return count;
  }).take(5);

  stream.listen(
    (data) {
      print('Data: $data');
    },
    onError: (error) {
      print('Error: $error');
    },
    onDone: () {
      print('Stream completat');
    },
  );
}

Explicació:

  • onError: Gestió d'errors en el stream.
  • onDone: Notificació quan el stream ha completat l'emissió d'esdeveniments.

Exercicis Pràctics

Exercici 1: Creació d'un Stream de Nombres Parells

Crea un stream que emeti els primers 10 nombres parells i imprimeixi cada valor.

Solució:

import 'dart:async';

void main() {
  Stream<int> evenStream = Stream<int>.periodic(Duration(seconds: 1), (count) => count * 2).take(10);

  evenStream.listen((data) {
    print('Even number: $data');
  });
}

Exercici 2: Gestió d'Errors en un Stream

Crea un stream que emeti valors de 0 a 4, però llanci un error quan el valor sigui 2. Gestiona l'error i imprimeix un missatge d'error.

Solució:

import 'dart:async';

void main() {
  Stream<int> errorStream = Stream<int>.periodic(Duration(seconds: 1), (count) {
    if (count == 2) {
      throw Exception('Error al valor 2');
    }
    return count;
  }).take(5);

  errorStream.listen(
    (data) {
      print('Data: $data');
    },
    onError: (error) {
      print('Error: $error');
    },
    onDone: () {
      print('Stream completat');
    },
  );
}

Conclusió

Els streams són una eina poderosa per gestionar seqüències d'esdeveniments asíncrons en Dart. Amb els coneixements adquirits en aquesta secció, ara pots crear, transformar i gestionar errors en streams. Aquests conceptes són fonamentals per treballar amb dades asíncrones de manera eficient i efectiva.

© Copyright 2024. Tots els drets reservats