Menu
CoddyTech

Перехват ошибок с помощью 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.

challenge icon

Задание

Средне

Сделай так, чтобы 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')),
          ],
        ),
      ),
    );
  }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Данные и сеть

Потренируйтесь самостоятельно: Онлайн-компилятор Flutter