Как реализовать асинхронность в Dart?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Асинхронность в Dart: полный справочник
В Dart асинхронность реализована через несколько механизмов, которые позволяют выполнять операции без блокирования основного потока. Это критично для мобильных приложений, где долгие операции (сетевые запросы, работа с БД) могут "заморозить" UI.
1. Future
Future — это представление значения, которое может быть доступно сейчас, в будущем или никогда (ошибка).
// Простой Future
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 2));
return "Данные загружены";
}
// Использование
fetchData().then((data) {
print(data);
}).catchError((error) {
print("Ошибка: $error");
});
2. Async/Await (рекомендуется)
Синтаксис async/await делает асинхронный код более читаемым и похожим на синхронный:
Future<String> fetchUserData() async {
try {
final response = await http.get(Uri.parse("https://api.example.com/user"));
if (response.statusCode == 200) {
return "Пользователь загружен";
} else {
throw Exception("Ошибка сервера");
}
} catch (e) {
print("Ошибка сети: $e");
return "Ошибка";
}
}
3. Stream
Stream — это последовательность асинхронных событий. Используется для обработки множества значений во времени.
// Создание Stream
Stream<int> countStream() async* {
for (int i = 1; i <= 5; i++) {
await Future.delayed(Duration(seconds: 1));
yield i; // Генерируем значение
}
}
// Слушание Stream
countStream().listen((value) {
print("Значение: $value");
});
// Или через async* с StreamBuilder в Flutter UI
StreamBuilder<int>(
stream: countStream(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text("Число: ${snapshot.data}");
}
return CircularProgressIndicator();
},
)
4. Параллельные операции
Для выполнения нескольких асинхронных операций параллельно используй Future.wait():
Future<void> loadMultipleData() async {
try {
final results = await Future.wait([
fetchUser(),
fetchPosts(),
fetchComments(),
]);
print("Все данные загружены: $results");
} catch (e) {
print("Ошибка: $e");
}
}
5. Isolate (для CPU-bound операций)
Для тяжёлых вычислений используй Isolate, чтобы не блокировать главный поток:
import "dart:isolate";
Future<int> heavyComputation(int count) async {
return await compute(_fibonacci, count);
}
int _fibonacci(int n) {
if (n <= 1) return n;
return _fibonacci(n - 1) + _fibonacci(n - 2);
}
6. BLoC паттерн (для Flutter)
В настоящих Flutter приложениях асинхронность часто управляется через BLoC:
class DataBloc extends Bloc<DataEvent, DataState> {
DataBloc() : super(DataInitial()) {
on<FetchData>((event, emit) async {
emit(DataLoading());
try {
final data = await _repository.fetchData();
emit(DataLoaded(data));
} catch (e) {
emit(DataError(e.toString()));
}
});
}
}
Правила и best practices
- Всегда используй await для Future
- Избегай вложенности (nested callbacks) — используй async/await
- Обрабатывай ошибки через try/catch
- Не забывай закрывать StreamSubscription через close()
- Для длительных операций используй Isolate или compute()
- В Flutter UI используй FutureBuilder, StreamBuilder или BLoC
Это основные способы работы с асинхронностью в Dart и Flutter. Выбор метода зависит от типа задачи.