Асинхронность в методах классов
Часть раздела Объектно-ориентированное программирование путешествия по 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Попробуйте сами
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
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн РепозиторийПотренируйтесь самостоятельно: Онлайн-компилятор Dart