Zgłaszanie błędu
Część sekcji Dane i sieć ścieżki Flutter w Coddy. Lekcja 11 z 27.
Błędy dotyczą nie tylko serwerów. Twoje własne funkcje mogą odmówić dalszego działania. Gdy funkcja otrzyma coś, z czym nie może pracować, zgłasza wyjątek:
Future<void> saveName(String name) async {
if (name.isEmpty) {
throw Exception('The name cannot be empty');
}
// zapisz imię
}throw zatrzymuje funkcję w tym miejscu, podobnie jak return, ale zwraca błąd zamiast wartości. Exception('...') to błąd z komunikatem opisującym, co poszło nie tak.
Funkcja, która ją wywołała, przechwytuje ten błąd za pomocą try i catch, tak samo jak błąd z fetch. Po zamienieniu na tekst Exception zaczyna się od Exception: , po którym następuje Twój komunikat.
Tak działa również prawdziwe fetch. Każda odpowiedź z serwera zawiera kod statusu: 200 oznacza OK, 404 oznacza, że nie znaleziono. Gdy kod statusu nie wynosi 200, Twój kod zgłasza wyjątek, dzięki czemu ekran nigdy nie wyświetla błędnej odpowiedzi tak, jakby były to dane:
final response = await http.get(Uri.parse(url));
if (response.statusCode != 200) {
throw Exception('The server answered ${response.statusCode}');
}
return response.body;Wyzwanie
ŁatwyStuknij Save, gdy pole jest puste: pojawi się Saved: bez imienia. Spraw, aby saveName odrzucała puste imię: po odczekaniu, jeśli name jest puste, rzuć Exception('The name cannot be empty'). Funkcja save już przechwytuje ten wyjątek i wyświetla komunikat.
Spróbuj swoich sił
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)),
],
),
),
);
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Dane i sieć
3Gdy wywołania kończą się niepowodzeniem
Przechwytywanie błędów za pomocą tryZgłaszanie błęduSprzątanie za pomocą finallyStan błędu w FutureBuilderPrzycisk „Spróbuj ponownie”Poćwicz samodzielnie: Kompilator Flutter online