Асинхронность в методах классов
Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 80 из 110.
Теперь, когда вы знаете, как обрабатывать асинхронную инициализацию с помощью фабричных методов, давайте рассмотрим, как сделать обычные методы экземпляра асинхронными. Это просто — просто добавьте async к любому методу и сделайте так, чтобы он возвращал Future.
class WeatherService {
String _location;
WeatherService(this._location);
Future<String> fetchTemperature() async {
await Future.delayed(Duration(seconds: 1));
return '22°C in $_location';
}
Future<void> updateLocation(String newLocation) async {
await Future.delayed(Duration(milliseconds: 500));
_location = newLocation;
print('Location updated to $_location');
}
}
Future<void> main() async {
var service = WeatherService('London');
var temp = await service.fetchTemperature();
print(temp);
await service.updateLocation('Paris');
}Асинхронные методы могут обращаться к переменным экземпляра и изменять их точно так же, как и обычные методы. Ключевое отличие заключается в том, что вызывающая сторона должна await результат. Методы, возвращающие Future<void>, не возвращают значение, но их все равно нужно ожидать, если вы хотите гарантировать их завершение перед продолжением.
Вы также можете комбинировать несколько асинхронных вызовов внутри метода или вызывать другие асинхронные методы из того же класса:
Future<String> getFullReport() async {
var temp = await fetchTemperature();
var humidity = await fetchHumidity();
return '$temp, Humidity: $humidity';
}Этот паттерн необходим для классов, которые взаимодействуют с внешними ресурсами — API, базами данных или любыми операциями, требующими времени.
Задание
ЛегкоДавайте создадим трекер фондового портфеля, который управляет ценами на акции и рассчитывает стоимость портфеля с помощью асинхронных методов! Вы создадите класс, который имитирует получение данных об акциях в реальном времени и объединяет несколько асинхронных операций для создания отчетов.
Вы организуете свой код в два файла:
portfolio.dart: Создайте классStockPortfolio, который отслеживает акции и их количество. Ваш класс должен иметь:- Приватную карту
Map<String, int>с именем_holdings, которая хранит символы акций и количество принадлежащих акций - Конструктор, который инициализирует
_holdingsкак пустую карту - Метод
addStock(String symbol, int quantity), который добавляет или обновляет владение акциями (не асинхронный) - Асинхронный метод
fetchPrice(String symbol), который возвращаетFuture<double>. Симулируйте задержку в 50 миллисекунд, затем верните цену, рассчитанную как: длина символа, умноженная на 25.5 - Асинхронный метод
getStockValue(String symbol), который возвращаетFuture<double>. Он должен ожидать выполненияfetchPriceдля символа, умножать результат на количество акций во владении и возвращать общую стоимость. Если символа нет в портфеле, верните 0.0 - Асинхронный метод
getTotalValue(), который возвращаетFuture<double>. Он должен рассчитать общую стоимость всех активов, ожидая выполненияgetStockValueдля каждой акции и суммируя результаты - Асинхронный метод
generateReport(), который возвращаетFuture<String>. Он должен построить отчет, показывающий стоимость каждой акции и общую сумму. Отформатируйте каждую строку как[symbol]: $[value](значение с 1 десятичным знаком), за которой следует последняя строкаTotal: $[totalValue](также с 1 десятичным знаком)
- Приватную карту
main.dart: Импортируйте файл портфеля и продемонстрируйте, как асинхронные методы работают вместе внутри класса:- Создайте экземпляр
StockPortfolio - Добавьте следующие активы:
AAPLс 10 акциями,GOOGLс 5 акциями,MSFTс 8 акциями - Выведите в консоль
Fetching portfolio data... - Дождитесь выполнения и выведите результат
generateReport()
- Создайте экземпляр
Обратите внимание, как generateReport() вызывает другие асинхронные методы внутри того же класса, и как каждый метод строится на основе других. Используйте toStringAsFixed(1) для форматирования десятичных значений!
Ожидаемый вывод:
Fetching portfolio data...
AAPL: $1020.0
GOOGL: $637.5
MSFT: $816.0
Total: $2473.5Шпаргалка
Чтобы сделать методы экземпляра асинхронными, добавьте ключевое слово async и возвращайте Future:
class WeatherService {
String _location;
WeatherService(this._location);
Future<String> fetchTemperature() async {
await Future.delayed(Duration(seconds: 1));
return '22°C in $_location';
}
Future<void> updateLocation(String newLocation) async {
await Future.delayed(Duration(milliseconds: 500));
_location = newLocation;
print('Location updated to $_location');
}
}Асинхронные методы могут обращаться к переменным экземпляра и изменять их. Вызывающая сторона должна использовать await для получения результата. Методы, возвращающие Future<void>, не возвращают значение, но их все равно нужно ожидать с помощью await, чтобы гарантировать завершение выполнения.
Асинхронные методы могут вызывать другие асинхронные методы внутри того же класса:
Future<String> getFullReport() async {
var temp = await fetchTemperature();
var humidity = await fetchHumidity();
return '$temp, Humidity: $humidity';
}Этот паттерн необходим для классов, которые взаимодействуют с внешними ресурсами, такими как API или базы данных.
Попробуйте сами
import 'portfolio.dart';
void main() async {
// TODO: Создайте экземпляр StockPortfolio
// TODO: Добавьте активы:
// - AAPL с 10 акциями
// - GOOGL с 5 акциями
// - MSFT с 8 акциями
// TODO: Выведите "Fetching portfolio data..."
// TODO: Ожидайте завершения и выведите результат generateReport()
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий