Lanciare un errore
Fa parte della sezione Dati e rete del percorso Flutter di Coddy. Lezione 11 di 27.
Gli errori non riguardano solo i server. Anche le tue funzioni possono rifiutarsi di continuare. Quando una funzione riceve qualcosa con cui non può lavorare, lancia un'eccezione:
Future<void> saveName(String name) async {
if (name.isEmpty) {
throw Exception('The name cannot be empty');
}
// salva il nome
}throw interrompe la funzione proprio lì, come return, ma restituisce un errore invece di un valore. Exception('...') è l'errore, con un messaggio che spiega cosa è andato storto.
Chi ha chiamato la funzione lo intercetta con try e catch, proprio come un errore proveniente da fetch. Quando viene convertita in testo, un'Exception inizia con Exception: , seguito dal tuo messaggio.
Anche un vero fetch funziona così. Ogni risposta di un server include un codice di stato: 200 significa OK, 404 significa non trovato. Se il codice non è 200, il tuo codice lancia un'eccezione, così lo schermo non mostra mai una risposta non valida come se fosse un dato:
final response = await http.get(Uri.parse(url));
if (response.statusCode != 200) {
throw Exception('The server answered ${response.statusCode}');
}
return response.body;Sfida
FacileTocca Save con il campo vuoto: viene visualizzato Saved: senza alcun nome. Fai in modo che saveName rifiuti un nome vuoto: dopo l'attesa, se name è vuoto, genera Exception('The name cannot be empty'). La funzione save lo intercetta già e mostra il messaggio.
Provalo tu
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)),
],
),
),
);
}
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Dati e rete
3Quando le chiamate falliscono
Gestire gli errori con tryLanciare un errorePulire con finallyLo stato di errore di FutureBuilderUn pulsante per riprovareEsercitati da solo: Compilatore Flutter online