J'essaie de détecter toutes les exceptions non gérées dans une application Flutter afin de pouvoir l'envoyer à un journaliste de crash. Il y a instructions sur la façon de procéder dans les documents Flutter . Je les ai suivis et j'ai ajouté deux bits de code à mon application pour intercepter les exceptions:
Détectez les erreurs Dart en enveloppant runApp
dans runZoned
:
runZoned<Future<void>>(
() async {
runApp(MyApp());
},
onError: (dynamic error, StackTrace stackTrace) {
print("=================== CAUGHT Dart ERROR");
// Send report
},
);
Détectez les erreurs de flottement en définissant FlutterError.onError
:
FlutterError.onError = (FlutterErrorDetails details) {
print("=================== CAUGHT FLUTTER ERROR");
// Send report
};
Cependant, lorsque je teste cela lors de l'exécution en lançant une exception à partir d'un bouton:
throw Exception("Just testing");
L'exception apparaît dans la console:
════════ Exception saisie par le geste ══════════════════════════════════════ _ L'exception _Exception suivante a été levée lors de la gestion d'un geste: Exception: test uniquement Lorsque l'exception a été levée, il s'agissait de la pile:
... etc
Mais je ne vois aucun signe de mes instructions d'impression (ERREUR Dart CAUGHT ou ERREUR FLUTTER CAUGHT), et définir des points d'arrêt sur ces lignes ne semble jamais frapper, donc je pense que mon code de gestion des exceptions ne l'attrape pas. Suis-je en train de manquer quelque chose?
Voici un exemple reproductible minimal (cliquez sur le bouton, ce qui lève une exception, mais il n'est pas détecté comme prévu):
import 'Dart:async';
import 'package:flutter/material.Dart';
void main() =>
runZoned<Future<void>>(
() async {
runApp(MyApp());
},
onError: (dynamic error, StackTrace stackTrace) {
print("=================== CAUGHT Dart ERROR");
// Send report
// NEVER REACHES HERE - WHY?
},
);
class MyApp extends StatefulWidget {
// This widget is the root of your application.
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
// This captures errors reported by the FLUTTER framework.
FlutterError.onError = (FlutterErrorDetails details) {
print("=================== CAUGHT FLUTTER ERROR");
// Send report
// NEVER REACHES HERE - WHY?
};
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: RaisedButton(
child: Text("Throw exception"),
onPressed: () {
throw Exception("This is a test exception");
},
),
),
),
);
}
}
D'accord, j'ai compris ce qui se passe. Jetez un œil à certains problèmes liés à Flutter:
l'outil de flottement est trop agressif pour intercepter les exceptions
Rendre le mode chaud un peu moins agressif à propos des erreurs de capture
Coupure sur les exceptions "non gérées" lorsqu'un débogueur est attaché
Il semble qu'en mode débogage, le framework flutter intercepte beaucoup d'exceptions, s'imprime sur la console (et s'affiche parfois dans l'interface utilisateur elle-même en rouge et jaune), mais ne relance pas - donc ils sont effectivement avalés et il y a aucun moyen pour votre propre code de les attraper. Mais, lorsque vous déployez en mode release, cela ne se produit pas. Donc, mon exemple reproductible minimal intercepte des exceptions lorsqu'il est construit en mode de publication.