Intercepter les erreurs avec try
Fait partie de la section Données et réseau du Journey Flutter de Coddy. Leçon 10 sur 27.
Un appel réseau peut échouer : le téléphone n’a pas de signal, le serveur est hors service, le chemin est incorrect. Lorsque fetch échoue, il lève une erreur : une ApiException, une petite classe en haut de api.dart avec un statusCode et un message. Une erreur que personne n’intercepte interrompt votre fonction et s’affiche en rouge dans la Console, tandis que la personne voit un indicateur de chargement qui ne s’arrête jamais.
Interceptez-la avec try et catch :
try {
final text = await fetch('/message');
// ne s’exécute que lorsque fetch a réussi
} catch (e) {
// ne s’exécute que lorsque fetch a levé une exception
print('It failed: $e');
}Dart exécute le bloc try. Si une instruction de ce bloc lève une erreur, Dart passe directement à catch, et e contient l’erreur. Les lignes qui suivent celle qui a échoué dans try ne sont jamais exécutées.
Placez le await lui-même dans try : c’est cette ligne qui lève l’erreur. Expliquez ensuite à la personne ce qui s’est passé, avec des mots, au lieu de provoquer un plantage.
Pour voir l’échec dans l’aperçu, écrivez offline = true; comme première ligne de main, puis appuyez sur Run. offline provient de api.dart : il fait échouer chaque appel comme si le téléphone n’avait pas de signal. Supprimez cette ligne avant d’appuyer sur Check.
Défi
MoyenFais en sorte que loadMessage survive à un échec de l’appel :
- place
fetchet lesetStatequi le suit dans un bloctry - dans
catch (e), arrête le spinner et définis le message surCould not load: $e
Essayez vous-même
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')),
],
),
),
);
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Données et réseau
3Quand les appels échouent
Intercepter les erreurs avec tryDéclencher une erreurNettoyer avec finallyL’état d’erreur de FutureBuilderUn bouton pour réessayerEntraînez-vous par vous-même : Compilateur Flutter en ligne