Stream
Stream - представляет из себя ассинхронный поток данных. Это противоположность Future, который возвращает всего один результат.
Типы Stream
У нас есть 2 типа потока данных и отличаются они по количеству слушателей.
Один слушатель
Мы можем создать функцию с асинхронным генератором, которая будет возвращать поток данных (Stream).
Stream<int> getData() async* {
yield 1; //отдаём данные
/* какой-то код */
yield 2; //отдаём ещё данные
/* какой-то код */
yield 3; //отдаём ещё данные
return; //говорим, что поток завершил выполнение и данных больше не будет
}
Таким образом мы получаем поток, который создаётся в момент вызова функции. Как только в потоке будет вызван return
, он будет закрыт автоматически, т.к. данных больше не будет.
Также мы можем создать StreamController
, который позволит нам вещать не из определённой функции, а из разных. Например, такой контроллер можно создать в классе и потом из разных методов вещать об изменениях.
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
.
Этот конструктор позволяет создать поток, который может иметь множество слуашетелей, а не одного.
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()
Обработка ошибок