Skip to content

Stream

Stream - представляет из себя ассинхронный поток данных. Это противоположность Future, который возвращает всего один результат.

Типы Stream

У нас есть 2 типа потока данных и отличаются они по количеству слушателей.

Один слушатель

Мы можем создать функцию с асинхронным генератором, которая будет возвращать поток данных (Stream).

dart
Stream<int> getData() async* {
    yield 1; //отдаём данные
    /* какой-то код */

    yield 2; //отдаём ещё данные
    /* какой-то код */
    yield 3; //отдаём ещё данные

    return; //говорим, что поток завершил выполнение и данных больше не будет
}

Таким образом мы получаем поток, который создаётся в момент вызова функции. Как только в потоке будет вызван return, он будет закрыт автоматически, т.к. данных больше не будет.

Также мы можем создать StreamController, который позволит нам вещать не из определённой функции, а из разных. Например, такой контроллер можно создать в классе и потом из разных методов вещать об изменениях.

dart
final controller = StreamController<int>(); //создаём поток, который отдаёт числа

controller.stream.listen((e) => print("Слушатель 1: $e")); //добавляем слушателя

controller.sink.add(1); //отдаём первое значение
controller.sink.add(2); //отдаём второе значение

controller.close(); //обязательно закрываем поток, когда он нам больше не нужен

DANGER

Если мы создаём StreamController, то обязательно помним, что его нужно закрыть, когда его цель будет выполнена.

Множество слушателей

Иногда необходим поток данных, который будет доступен не только одному слушателю, а множеству слушателей. Для этого у нас есть StreamController.broadcast.
Этот конструктор позволяет создать поток, который может иметь множество слуашетелей, а не одного.

dart
final controller = StreamController<int>.broadcast(); //создаём поток

controller.stream.listen((e) => print("Слушатель 1: $e")); //первый подписчик
controller.stream.listen((e) => print("Слушатель 2: $e")); //второй подписчик

controller.add(10);

Таким образом мы можем создавать потоки, которые будут вещать всем, кто слушает. Это полезно, например, когда мы получаем данные через сокеты и их надо передать в разные части приложения.

Полезные методы

  • map() Трансформирует данные
  • where() Фильтрует события
  • take(n) Берёт первые n событий
  • skip(n) Пропускает первые n событий
  • distinct() Пропускает повторяющиеся значения
  • debounceTime() Задержка между событиями (через RxDart)
  • asyncMap() Асинхронная трансформация
  • handleError() Обработка ошибок