Lançando um erro
Parte da seção Dados e rede do Journey de Flutter da Coddy. Lição 11 de 27.
Erros não acontecem apenas em servidores. Suas próprias funções podem se recusar a continuar. Quando uma função recebe algo com que não consegue trabalhar, ela lança um erro:
Future<void> saveName(String name) async {
if (name.isEmpty) {
throw Exception('The name cannot be empty');
}
// salvar o nome
}throw interrompe a função naquele ponto, como return, mas devolve um erro em vez de um valor. Exception('...') é o erro, com uma mensagem que diz o que deu errado.
Quem chamou a função captura o erro com try e catch, exatamente como um erro de fetch. Convertida em texto, uma Exception começa com Exception: , seguida da sua mensagem.
É assim que um fetch real também funciona. Toda resposta de um servidor vem com um código de status: 200 significa OK, 404 significa não encontrado. Quando não é 200, seu código lança um erro, para que a tela nunca mostre uma resposta com falha como se fosse um dado:
final response = await http.get(Uri.parse(url));
if (response.statusCode != 200) {
throw Exception('The server answered ${response.statusCode}');
}
return response.body;Desafio
FácilToque em Save com o campo vazio: ele mostra Saved: sem nenhum nome. Faça com que saveName recuse um nome vazio: após a espera, se name estiver vazio, lance Exception('The name cannot be empty'). A função save já captura isso e mostra a mensagem.
Experimente você mesmo
import 'package:flutter/material.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: NameScreen(),
);
}
}
class NameScreen extends StatefulWidget {
const NameScreen({super.key});
@override
State<NameScreen> createState() => _NameScreenState();
}
class _NameScreenState extends State<NameScreen> {
final controller = TextEditingController();
String status = '';
@override
void dispose() {
controller.dispose();
super.dispose();
}
Future<void> saveName(String name) async {
await Future.delayed(const Duration(seconds: 1));
}
Future<void> save() async {
try {
await saveName(controller.text);
setState(() {
status = 'Saved: ${controller.text}';
});
} catch (e) {
setState(() {
status = '$e';
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: controller,
decoration: const InputDecoration(labelText: 'Name'),
),
const SizedBox(height: 16),
ElevatedButton(onPressed: save, child: const Text('Save')),
const SizedBox(height: 16),
Text(status, style: const TextStyle(fontSize: 18)),
],
),
),
);
}
}
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
3Quando as chamadas falham
Capturando erros com tryLançando um erroFazendo a limpeza com finallyO estado de erro do FutureBuilderUm botão para tentar novamentePratique por conta própria: Compilador de Flutter online