Menu
Coddy logo textTech

Stream Controllers

Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 78 sur 110.

Alors que les générateurs async* sont excellents pour créer des flux avec des données prédéfinies, vous avez parfois besoin de plus de contrôle - comme ajouter des données à un flux à partir de différentes parties de votre code. C'est là que StreamController intervient.

Un StreamController agit comme un gestionnaire pour un stream. Il vous donne un « sink » pour ajouter des données et un « stream » auquel les écouteurs peuvent s'abonner :

import 'dart:async';

void main() {
  var controller = StreamController<String>();
  
  // Écouter le flux
  controller.stream.listen((data) {
    print('Received: $data');
  });
  
  // Ajouter des données via le sink
  controller.add('Hello');
  controller.add('World');
  
  controller.close();  // Toujours fermer une fois terminé
}

La méthode add() ajoute de nouvelles valeurs dans le flux, et tous les écouteurs les reçoivent immédiatement. Vous devriez toujours appeler close() lorsque vous avez terminé pour libérer les ressources.

Par défaut, un stream ne peut avoir qu'un seul écouteur. Pour plusieurs écouteurs, utilisez un contrôleur de diffusion (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();
}

Les StreamControllers sont essentiels en POO pour construire des classes pilotées par les événements - comme notifier plusieurs parties de votre application lorsque les données changent, gérer les actions de l'utilisateur ou gérer les mises à jour en temps réel au sein de vos objets.

challenge icon

Défi

Facile

Construisons un système de concentrateur de messages qui permet à plusieurs abonnés de recevoir des messages en temps réel ! Vous utiliserez un StreamController pour gérer le flux de messages et démontrer comment les flux de diffusion (broadcast streams) permettent d'avoir plusieurs écouteurs.

Vous organiserez votre code en deux fichiers :

  • message_hub.dart : Créez une classe MessageHub qui gère la distribution des messages à l'aide d'un StreamController. Votre concentrateur doit :
    • Utiliser un StreamController<String> de type broadcast en interne afin que plusieurs écouteurs puissent s'abonner
    • Fournir un getter nommé messages qui renvoie le flux pour que les écouteurs puissent s'y abonner
    • Avoir une méthode broadcast(String message) qui ajoute un message au flux
    • Avoir une méthode shutdown() qui ferme le contrôleur
  • main.dart : Importez votre concentrateur de messages et mettez en place un scénario avec plusieurs abonnés écoutant le même flux :
    • Créez une instance de MessageHub
    • Ajoutez un premier écouteur qui affiche les messages au format : Subscriber A: [message]
    • Ajoutez un second écouteur qui affiche les messages au format : Subscriber B: [message]
    • Diffusez trois messages : Hello everyone, Welcome to the hub, et Goodbye
    • Fermez le concentrateur

N'oubliez pas d'importer dart:async dans votre fichier de concentrateur de messages pour accéder à StreamController. Remarquez comment les deux abonnés reçoivent chaque message diffusé - c'est toute la puissance des flux de diffusion !

Sortie attendue :

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

Aide-mémoire

Un StreamController gère un flux (stream), offrant un contrôle sur le moment et la manière dont les données sont ajoutées. Il vous fournit un « sink » (puits) pour ajouter des données et un « stream » auquel les auditeurs peuvent s'abonner.

Utilisation basique :

import 'dart:async';

var controller = StreamController<String>();

// Listen to the stream
controller.stream.listen((data) {
  print('Received: $data');
});

// Add data through the sink
controller.add('Hello');
controller.add('World');

controller.close();  // Always close when done

La méthode add() pousse de nouvelles valeurs dans le flux. Les auditeurs les reçoivent immédiatement. Appelez toujours close() lorsque vous avez terminé pour libérer les ressources.

Par défaut, un flux ne peut avoir qu'un seul auditeur. Pour plusieurs auditeurs, utilisez un contrôleur de diffusion (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();

Les StreamControllers sont essentiels pour créer des classes pilotées par les événements, notifier plusieurs parties de votre application lorsque les données changent, gérer les actions des utilisateurs ou gérer les mises à jour en temps réel.

Essayez vous-même

import 'message_hub.dart';

void main() {
  // TODO: Créer une instance de MessageHub
  
  // TODO: Ajouter un premier écouteur qui affiche : Subscriber A: [message]
  
  // TODO: Ajouter un deuxième écouteur qui affiche : Subscriber B: [message]
  
  // TODO: Diffuser trois messages :
  // - "Hello everyone"
  // - "Welcome to the hub"
  // - "Goodbye"
  
  // TODO: Fermer le hub
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet