Основы Streams
Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 77 из 110.
В то время как Future предоставляет одно значение, Stream предоставляет последовательность значений с течением времени. Представьте его как трубу, которая может выдавать несколько фрагментов данных — это идеально подходит для событий, обновлений в реальном времени или обработки данных по частям.
Вы можете создать простой поток, используя Stream.fromIterable() или асинхронную функцию-генератор с async* и yield:
Stream<int> countToThree() async* {
yield 1;
yield 2;
yield 3;
}
Future<void> main() async {
await for (var number in countToThree()) {
print(number);
}
}
// Вывод: 1, 2, 3Ключевое слово async* помечает функцию, которая возвращает Stream, а yield выдает каждое значение. Чтобы использовать поток, используйте await for, который обрабатывает каждое значение по мере его поступления.
Вы также можете прослушивать поток с помощью метода listen(), который принимает функцию обратного вызова:
Stream<String> greetings() async* {
yield 'Hello';
yield 'Hi';
yield 'Hey';
}
void main() {
greetings().listen((message) {
print(message);
});
}Ключевое отличие от Futures: Future завершается один раз с единственным значением, в то время как Stream может выдавать множество значений до своего завершения. Это делает Streams идеальными для обработки непрерывных данных, таких как взаимодействие с пользователем, показания датчиков или данные, поступающие частями.
Задание
ЛегкоДавайте создадим систему таймера обратного отсчета, которая передает значения с течением времени с помощью потоков (streams)! Вы создадите класс, который генерирует последовательность чисел обратного отсчета, демонстрируя, как потоки доставляют несколько значений, а не только одно.
Вы организуете свой код в двух файлах:
countdown.dart: Создайте классCountdown, который генерирует потоки обратного отсчета. Ваш класс должен иметь:- Поле
start(int), в котором хранится начальное число для обратного отсчета - Конструктор, принимающий начальное число
- Метод
countDown(), который возвращаетStream<int>. Используйтеasync*иyieldдля передачи чисел отstartдо0(включительно) - Метод
countDownWithMessage(), который возвращаетStream<String>. Он должен передавать строки в формате'T-minus [number]'для каждого числа отstartдо1, а затем передать'Liftoff!'в качестве финального значения
- Поле
main.dart: Импортируйте файл с обратным отсчетом и продемонстрируйте работу обоих методов потока. Ваша функция main должна быть асинхронной (async) и:- Создавать экземпляр
Countdown, начиная с3 - Выводить на печать
'Number countdown:' - Использовать
await forдля итерации поcountDown()и вывода каждого числа - Выводить пустую строку
- Выводить на печать
'Launch sequence:' - Использовать
await forдля итерации поcountDownWithMessage()и вывода каждого сообщения
- Создавать экземпляр
Обратите внимание, как каждый оператор yield передает значение через поток, а await for обрабатывает каждое значение по мере его поступления. В отличие от Future, который доставляет один результат, ваши потоки будут передавать несколько значений последовательно!
Ожидаемый результат:
Number countdown:
3
2
1
0
Launch sequence:
T-minus 3
T-minus 2
T-minus 1
Liftoff!Шпаргалка
Stream доставляет последовательность значений с течением времени, в отличие от Future, который возвращает одно значение. Потоки (Streams) идеально подходят для обработки событий, обновлений в реальном времени или поэтапной обработки данных.
Создайте поток, используя функцию асинхронного генератора с async* и yield:
Stream<int> countToThree() async* {
yield 1;
yield 2;
yield 3;
}Используйте поток с помощью цикла await for:
Future<void> main() async {
await for (var number in countToThree()) {
print(number);
}
}Кроме того, можно использовать метод listen() с функцией обратного вызова:
void main() {
greetings().listen((message) {
print(message);
});
}Вы также можете создать поток из итерируемого объекта, используя Stream.fromIterable().
Попробуйте сами
import 'countdown.dart';
Future<void> main() async {
// TODO: Создайте экземпляр Countdown, начиная с 3
// TODO: Выведите 'Number countdown:'
// TODO: Используйте await for для итерации по countDown() и выведите каждое число
// TODO: Выведите пустую строку
// TODO: Выведите 'Launch sequence:'
// TODO: Используйте await for для итерации по countDownWithMessage() и выведите каждое сообщение
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыБиблиотеки и импортВведение в ООПКлассы и объектыКлючевое слово thisМетодыПеременные экземпляраОсновы конструкторовИтоги — Простой калькулятор4Null-безопасность
Введение в Null-безопасностьNullable и Non-Nullable типыОператоры ? и !Ключевое слово Late и Null-безопасностьNull-aware операторыNull-безопасность в классахИтоги — Система профилей пользователей7Абстрактные классы и интерфейсы
Абстрактные классыАбстрактные методыИнтерфейсы в DartНеявные интерфейсыРеализация против наследованияМножественные интерфейсыИтоги — Калькулятор фигур10Коллекции и обобщения
Обзор List, Set, MapТипобезопасные коллекцииОбобщенные классыОбобщенные методыОграничения обобщенийIterable и IteratorИтоги: Обобщенное хранилище13Продвинутые концепции ООП
Композиция против наследованияМетоды расширенияВызываемые классыЗапечатанные классы (Dart 3)Записи (Dart 3)Паттерны и сопоставление (3.0)Перечисления с методами16Проект: Управление библиотекой
Обзор проектаКлассы Book и User2Конструкторы в Dart
Конструктор по умолчаниюИменованные конструкторыСписки инициализацииКонстантные конструкторыФабричные конструкторыПеренаправляющие конструкторыИтоги — Shape Builder5Инкапсуляция
Публичные и приватные членыСоглашение о префиксе _Приватность на уровне библиотекГеттеры и сеттеры: подробный разборСкрытие данныхИтоги — Записи о студентах8Mixins
Введение в MixinsСоздание MixinsИспользование нескольких MixinsКлючевое слово on в MixinsMixin и наследованиеMixin и интерфейсИтоги: Система животных11Специальные методы
Переопределение toString()Переопределение hashCode и ==Интерфейс ComparableМетод call()Переопределение noSuchMethodПовторение — Пользовательская коллекция14Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy3Свойства классов
Члены экземпляра и статические членыПоля Final и ConstПеременные LateСтатические методы и поляГеттеры и сеттерыИтоги — Менеджер банковского счета6Наследование
Основы наследованияКлючевое слово superПереопределение методовАннотация @overrideКлючевое слово final для классовКонструкторы и наследованиеИтоги: Иерархия сотрудников9Полиморфизм
Основы полиморфизмаПолиморфизм через интерфейсыПроверка типов во время выполненияОператоры is и asКлючевое слово covariantИтоги — Обработчик платежей12Асинхронное ООП
Futures и async/awaitОсновы StreamsКонтроллеры StreamАсинхронные конструкторыАсинхронность в методах классовИтоги — Data Fetcher15Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий