Что такое StreamController в Dart?

«Что такое StreamController в Dart?» — вопрос из категории Асинхронность, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

StreamController — это класс из dart:async, который выступает в роли источника и менеджера для Stream. Он предоставляет интерфейс для добавления событий в поток (через sink) и для создания подписок на этот поток (через stream). Это основной инструмент для создания собственных потоков данных.

Ключевые компоненты:

  • stream: Геттер, возвращающий объект Stream, на который можно подписаться.
  • sink: Геттер, возвращающий объект Sink ("сток"), используемый для добавления данных или ошибок в поток.
  • add(event): Основной метод для отправки данных в поток.
  • close(): Закрывает контроллер и поток. После этого нельзя добавлять новые события.

Практический пример — создание простого таймера:

import 'dart:async';

class CountdownService {
  final StreamController<int> _controller = StreamController<int>.broadcast();
  Timer? _timer;
  int _count = 10;

  Stream<int> get countStream => _controller.stream;

  void start() {
    _timer = Timer.periodic(Duration(seconds: 1), (timer) {
      if (_count > 0) {
        _controller.add(_count); // Отправляем текущее значение в поток
        _count--;
      } else {
        _controller.add(0);
        _controller.close(); // Важно закрыть контроллер и освободить ресурсы
        timer.cancel();
      }
    });
  }

  void dispose() {
    _timer?.cancel();
    _controller.close();
  }
}
// Использование во Flutter с StreamBuilder:
// StreamBuilder<int>(
//   stream: countdownService.countStream,
//   builder: (context, snapshot) => Text('${snapshot.data ?? 10}'),
// )

Типы контроллеров:

  • StreamController(): Создает одиночный поток подписки.
  • StreamController.broadcast(): Создает широковещательный поток, позволяющий множественным слушателям подписываться.

Важно: Всегда закрывайте StreamController (например, в методе dispose() у StatefulWidget), чтобы предотвратить утечки памяти.