Einen Fehler auslösen
Teil des Abschnitts Daten und Netzwerk der Flutter-Journey von Coddy. Lektion 11 von 27.
Fehler gibt es nicht nur auf Servern. Auch deine eigenen Funktionen können sich weigern, weiterzumachen. Wenn eine Funktion etwas erhält, womit sie nicht arbeiten kann, wirft sie einen Fehler:
Future<void> saveName(String name) async {
if (name.isEmpty) {
throw Exception('The name cannot be empty');
}
// den Namen speichern
}throw beendet die Funktion genau dort, wie return, gibt aber statt eines Werts einen Fehler zurück. Exception('...') ist der Fehler mit einer Meldung, die erklärt, was schiefgelaufen ist.
Wer die Funktion aufgerufen hat, fängt den Fehler mit try und catch ab, genau wie einen Fehler von fetch. Als Text beginnt eine Exception mit Exception: , gefolgt von deiner Meldung.
So funktioniert auch ein echtes fetch. Jede Antwort eines Servers enthält einen Statuscode: 200 bedeutet OK, 404 bedeutet nicht gefunden. Wenn der Statuscode nicht 200 ist, wirft dein Code einen Fehler, damit der Bildschirm eine fehlerhafte Antwort niemals so anzeigt, als wären darin Daten enthalten:
final response = await http.get(Uri.parse(url));
if (response.statusCode != 200) {
throw Exception('The server answered ${response.statusCode}');
}
return response.body;Aufgabe
EinfachTippe bei leerem Feld auf Save: Es wird Saved: ohne Namen angezeigt. Sorge dafür, dass saveName einen leeren Namen zurückweist: Wenn name nach der Wartezeit leer ist, löse Exception('The name cannot be empty') aus. Die Funktion save fängt den Fehler bereits ab und zeigt die Meldung an.
Probier es selbst
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)),
],
),
),
);
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Daten und Netzwerk
2Ladebildschirme
Ein Spinner während des LadensFutureBuilder kennenlernenEinmalig in initState ladenDaten per Button neu ladenZum Aktualisieren nach unten ziehen5Datumsangaben und Preise
Datumsangaben mit DateFormatUhrzeiten mit DateFormatPreise mit NumberFormat3Wenn Aufrufe fehlschlagen
Fehler mit try abfangenEinen Fehler auslösenAufräumen mit finallyDer Fehlerzustand von FutureBuilderEine Erneut-versuchen-SchaltflächeÜbe selbstständig: Online-Flutter-Compiler