Menu
CoddyTech

Состояние ошибки в FutureBuilder

Часть раздела Данные и сеть путешествия по Flutter на Coddy. Урок 13 из 27.

FutureBuilder перехватывает ошибки за вас. Когда его future выбрасывает исключение, приложение не падает: builder запускается снова, при этом snapshot.hasError получает значение true, а snapshot.error содержит выброшенное значение.

Это означает, что у каждого экрана загрузки есть три состояния, и builder обрабатывает каждое из них:

if (snapshot.hasError) {
  return Text('Could not load: ${snapshot.error}');
}
if (snapshot.hasData) {
  return Text(snapshot.data!);
}
return const CircularProgressIndicator();

Ошибка, данные и всё ещё выполняющаяся загрузка. Builder, который учитывает только данные, будет показывать индикатор загрузки бесконечно, если вызов завершится ошибкой, потому что данных так и не появится.

Разместите каждую проверку перед тем return, который скроет её. Если return индикатора загрузки для случая «нет данных» стоит первым, строка с ошибкой ниже никогда не выполнится.

Чтобы увидеть сбой в предварительном просмотре, добавьте offline = true; первой строкой в main и нажмите «Запустить». offline берётся из api.dart: он заставляет каждый вызов завершаться ошибкой, как если бы на телефоне не было сигнала. Удалите эту строку, прежде чем нажимать «Проверить».

challenge icon

Задание

Средне

Без подключения этот экран будет бесконечно показывать индикатор загрузки. Добавь обработку ошибки в билдер: когда snapshot.hasError, показывай Could not load: , за которым следует snapshot.error, размером 20.

Попробуйте сами

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> {
  late Future<String> _message;

  @override
  void initState() {
    super.initState();
    _message = fetch('/message');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FutureBuilder<String>(
          future: _message,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return Text(snapshot.data!, style: const TextStyle(fontSize: 24));
            }
            return const CircularProgressIndicator();
          },
        ),
      ),
    );
  }
}
quiz iconПроверьте себя

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

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

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