Перехват ошибок с помощью try
Часть раздела Данные и сеть путешествия по Flutter на Coddy. Урок 10 из 27.
Сетевой запрос может завершиться с ошибкой: на телефоне нет сигнала, сервер недоступен, путь указан неверно. Когда fetch завершается с ошибкой, он выбрасывает ошибку: ApiException — небольшой класс в начале файла api.dart с полями statusCode и message. Ошибка, которую никто не перехватывает, прерывает выполнение вашей функции и отображается в Console красным цветом, а пользователь видит бесконечно крутящийся индикатор.
Перехватите её с помощью try и catch:
try {
final text = await fetch('/message');
// выполняется только при успешном выполнении fetch
} catch (e) {
// выполняется только если fetch выбросил исключение
print('It failed: $e');
}Dart выполняет блок try. Если что-то внутри него выбрасывает ошибку, Dart сразу переходит к catch, а e содержит ошибку. Строки после той, на которой произошла ошибка, внутри try не выполняются.
Поместите сам await внутрь try: именно эта строка выбрасывает ошибку. Затем объясните пользователю, что произошло, словами, вместо того чтобы допустить сбой приложения.
Чтобы увидеть ошибку в предпросмотре, напишите offline = true; первой строкой в main и нажмите Run. offline находится в api.dart: он заставляет каждый запрос завершаться с ошибкой, как если бы на телефоне не было сигнала. Удалите эту строку перед нажатием Check.
Задание
СреднеСделай так, чтобы loadMessage обрабатывала неудачный вызов:
- помести
fetchи следующий за нимsetStateв блокtry - в
catch (e)останови индикатор загрузки и установи сообщениеCould not load: $e
Попробуйте сами
import 'package:flutter/material.dart';
import 'api.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: MessageScreen(),
);
}
}
class MessageScreen extends StatefulWidget {
const MessageScreen({super.key});
@override
State<MessageScreen> createState() => _MessageScreenState();
}
class _MessageScreenState extends State<MessageScreen> {
String message = 'No message yet';
bool loading = false;
Future<void> loadMessage() async {
setState(() {
loading = true;
});
final text = await fetch('/message');
setState(() {
message = text;
loading = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
loading
? const CircularProgressIndicator()
: Text(message, style: const TextStyle(fontSize: 24)),
const SizedBox(height: 24),
ElevatedButton(onPressed: loadMessage, child: const Text('Load message')),
],
),
),
);
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Данные и сеть
1Future (асинхронные результаты)
Значение, которое появится позжеОжидание с async и awaitФункции, возвращающие FutureПрактический API Coddy3Когда вызовы завершаются ошибкой
Перехват ошибок с помощью tryВыбрасывание ошибкиОчистка с помощью finallyСостояние ошибки в FutureBuilderКнопка «Попробовать снова»Потренируйтесь самостоятельно: Онлайн-компилятор Flutter