Menu
CoddyTech

Capturando erros com try

Parte da seção Dados e rede do Journey de Flutter da Coddy. Lição 10 de 27.

Uma chamada de rede pode falhar: o celular está sem sinal, o servidor está fora do ar, o caminho está errado. Quando fetch falha, ela lança um erro: uma ApiException, uma pequena classe no início de api.dart com um statusCode e uma message. Um erro que ninguém captura interrompe sua função e aparece como um erro em vermelho no Console, e a pessoa vê um indicador de carregamento que nunca termina.

Capture-o com try e catch:

try {
  final text = await fetch('/message');
  // só é executado quando fetch funciona
} catch (e) {
  // só é executado quando fetch lança uma exceção
  print('It failed: $e');
}

Dart executa o bloco try. Se algo nele lançar um erro, Dart vai direto para catch, e e guarda o erro. As linhas após a que falhou em try nunca são executadas.

Coloque o próprio await dentro de try: é essa linha que lança o erro. Em seguida, explique à pessoa o que aconteceu, em palavras, em vez de deixar o programa travar.

Para ver a falha na prévia, escreva offline = true; como a primeira linha de main e pressione Executar. offline vem de api.dart: ele faz todas as chamadas falharem como se o celular estivesse sem sinal. Remova a linha antes de pressionar Verificar.

challenge icon

Desafio

Médio

Faça com que loadMessage continue funcionando mesmo quando uma chamada falhar:

  • coloque o fetch e o setState que vem depois dele em um bloco try
  • em catch (e), pare o indicador de carregamento e defina a mensagem como Could not load: $e

Experimente você mesmo

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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Dados e rede

Pratique por conta própria: Compilador de Flutter online