Capture method of Flutter end anomaly
Abnormalities in Flutter can be divided into synchronous and asynchronous abnormalities. The types of abnormalities are as follows:
-
RangeError; The dart abnormal
-
FlutterErrorDetails; Page rendering exception
-
MissingPluginException; Service exceptions
-
DioError; Dio Request Exception
But by the error. RuntimeType. ToString () to obtain the exception type;
Synchronous exceptions can be caught using a try-catch. Asynchronous exceptions need to be caught using other FLUTTER apis. The following lists the common methods of flutter exception catching:
Catch exceptions using try-catchf
Dart provides a try-catch block similar to the Java and OC languages, and is relatively simple to use:
Try {// throw Exception("This is a test Exception "); } catch (error,stack) {Copy the code
The Flutter frame layer catches an exception
The Flutter framework allows us to capture anomalies in many key ways. As an example, Flutter automatically displays an error screen when our layout is out of bounds or out of specification. This is because Flutter has added exception catching when executing the build method.
@override void performRebuild() { ... Built = build(); Built = errorWidget. builder(_debugReportException('building $this', e, stack)); }... }Copy the code
As you can see, the default behavior of Flutter is to pop an ErrorWidget when an exception occurs. But what should WE do if we want to catch the exception ourselves and report it to the alarm platform? Let’s go to the _debugReportException() method:
FlutterErrorDetails _debugReportException( String context, dynamic exception, StackTrace stack, {InformationCollector InformationCollector}) {final FlutterErrorDetails details = FlutterErrorDetails( exception: exception, stack: stack, library: 'widgets library', context: context, informationCollector: informationCollector, ); // Reports an error FlutterError. ReportError (details); return details; }Copy the code
Error reported by FlutterError. ReportError
static void reportError(FlutterErrorDetails details) { ... if (onError ! = null) onError(details); // call onError callback}Copy the code
OnError is a static attribute of FlutterError, which has a default handler, dumpErrorToConsole. It is clear that if we want to report the exception ourselves, we only need to provide a custom error handling callback, such as:
void main() { FlutterError.onError = (FlutterErrorDetails details) { reportError(details); }; . }Copy the code
Now that we can handle the exceptions that Flutter catches for us, let’s see how to catch other exceptions.
Also: If we need to customize the error page, we need to override errorWidget.Builder:
Errorwidget. builder = (FlutterErrorDetails details) {return MaterialApp(title: 'Error Widget', theme: ThemeData(primarySwatch: colors.red,), home: Scaffold(appBar: appBar (title: Text('Widget render exception!! '), ), body: getErrorWidget(details.toString()), ), ); };Copy the code
Use the Future API to catch exceptions
The Future API provides a catchError method to catch asynchronous exceptions thrown when using the Future:
Future.delayed(Duration(seconds: 1)).then((e)=>print(e.tostring ())).catchError((){// handle exception}Copy the code
Catch an unhandled exception with a Zone
Flutter provides zone. runZoned methods (Dart :async package) to capture all unprocessed exception information. Flutter can also capture, intercept, or modify code behavior.
R runZoned<R>(R body(), {
Map zoneValues,
ZoneSpecification zoneSpecification,
Function onError,
})
Copy the code
ZoneValues is the private attribute of a Zone. ZoneSpecification is the configuration information of a Zone. You can customize some code behaviors.
If the developer provides the onError callback methods or by ZoneSpecification. HandleUncaughtError specifies the error handling callback methods, then this Zone will become a error Zone, either synchronous or asynchronous environment, This error zone is called whenever an uncaught exception occurs:
runZoned(() {
runApp(MyApp());
}, onError: (Object obj, StackTrace stack) {
var details=makeDetails(obj,stack);
reportError(details);
});
Copy the code
Note:
This is because the Flutter framework catches many exceptions in Debug mode and prints them to the console (sometimes shown in red on the UI) without rethrowing them, so your code cannot catch these exceptions. The solution is to run it in Release mode!
Best practices for Flutter anomaly collection
Currently, exception information can be collected as follows:
Automatically collect
- Automatic collection means catching exceptions that are not caught by global code;
- Global capture of flutter using runZoned mode;
Manual collection
- Use try-catch to collect exceptions for specified code blocks;
Flutter exception capture key code
Red screen exception capture
The following code is placed in main.dart, outside the main() function
Body Widget getErrorWidget(Dynamic Details) {return Container(color: color.white, child: Center(child: Text(" error!! ,style: TextStyle(color: Colors.black,fontSize: 26)), ) ); }Copy the code
The following code is placed in the main() function
/ / / custom red screen abnormal ErrorWidget builder = (FlutterErrorDetails details) {ExceptionReporter. ReportError (details, null); return MaterialApp( title: 'Error Widget', theme: ThemeData( primarySwatch: Colors.red, ), home: Scaffold( appBar: AppBar(title: Text('Widget rendering exception!! '), ), body: getErrorWidget(details.toString()), ), ); };Copy the code
Other exception catching
The following code is placed in the main() function
bool isProduction = const bool.fromEnvironment("dart.vm.product"); FlutterError.onError = (FlutterErrorDetails details) async { if (isProduction) { Zone.current.handleUncaughtError(details.exception, details.stack); } else { FlutterError.dumpErrorToConsole(details); }}; / / / initializes the Sentry ExceptionReporter. InitSentryWithUid (' 1001 '); runZoned(() async { runApp(MyApp()); }, onError: (dynamic error,StackTrace stackTrace) async { showToast(">>>"+error.toString()); / / report Sentry ExceptionReporter reportError (error, stackTrace); });Copy the code
Exception_reporter.dart code file:
import 'package:flutter_study_app/utils/platform_utils.dart'; import 'package:sentry/sentry.dart'; import 'package:sentry/sentry.dart' as Sentry; Var _sentryClient = Sentry. SentryClient (DSN: 'http://[email protected]:9000/5'); Class ExceptionReporter {/// Initialize Sentry /// Fill in uid static void initSentryWithUid(String UID) {_sentryClient.userContext = Sentry.User(id: uid); } static Future<Null> reportError(dynamic error, dynamic stackTrace) async { Map<String, dynamic> deviceInfo = await PlatformUtils .getMapFromDeviceInfo(); String appVersion = await PlatformUtils.getAppVersion(); / / / custom need to report the information Map < String, dynamic > _errMap = {' \ n \ n error type: error. RuntimeType. The toString (), '\ n \ n application version: AppVersion, '\n device information \n': deviceInfo, '\n Error message \n': error.toString()}; / / / / _sentryClient Sentry reported. CaptureException (exception: '$_errMap stackTrace: stackTrace); final SentryResponse response = await _sentryClient.capture( event: Event( exception: '$_errMap', stackTrace: stackTrace, ), ); Response. isSuccessful {print('Success! Event ID: ${response.eventId}'); } else { print('Failed to report to Sentry.io: ${response.error}'); }}}Copy the code
Calculation of FlutterException rate
FlutterException rate = Number of exception occurrences/FLUTTER page PV
Numerator: Number of exception occurrences (whitelisted)
FlutterError. OnError is called by Flutter assert, try-catch, and exception logic
Monitor the number of exceptions by redirecting FlutterError. OnError to its own method and report exception information
Denominator: FLUTTER page PV
References:
www.it1352.com/2028487.htm…
Because Chinese website
www.jianshu.com/p/d51395d57…
Blog.csdn.net/zhaowei121/…