0 x00 preface

Development of Flutter, will certainly encounter Flutter error page, you can let us know at the time of development clearly code is unusual, but, if there is abnormal release out of the APP, then this error page is very unfriendly, actually this error page can be customized, this article tells you how to custom error page!

0x01 Error page of Flutter

This is the error page we often see:

0x02 Customizes a Flutter error page

To display the error page of a Flutter as a custom page, just set the ErrorWidget Builder. The code is as follows:

ErrorWidget.builder = (FlutterErrorDetails flutterErrorDetails){
        print(flutterErrorDetails.toString());
        return Center(
          child: Text("Flutter was distracted.")); };Copy the code

Errorwidget. builder returns a Widget that will be displayed when a Flutter fails. Here is our custom error page, which is much friendlier than Flutter:

0x03 github

The code for this article: github.com/koudle/GDG_…

Github address: github.com/koudle/GDG_…

0x04 ErrorWidget source analysis

Dart lines 3581 to 3630. The ErrorWidget constructor takes an exception object and returns a RenderBox with an Exception message. The error page we see for Flutter is this RenderBox.

Class ErrorWidget extends LeafRenderObjectWidget {/// Creates a Widget that displays an error message. Exception is an argument to the constructor. ErrorWidget(Object exception) : message = _stringify(exception), super(key: UniqueKey()); / / ErrorWidgetBuilder. The default setting is ErrorWidget builder, We can set it to our own static ErrorWidgetBuilder Builder = (FlutterErrorDetails details) => ErrorWidget(details.exception); /// The message to display. final String message; // Convert the exception Object to string static string _stringify(Object exception) {try {return exception.toString();
    } catch (e) { } // ignore: empty_catches
    return 'Error'; } renderbox-override RenderBox createRenderObject(BuildContext context) => RenderErrorBox(message); @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties.add(StringProperty('message', message, quoted: false)); }}Copy the code

0x05 Calls source code analysis of ErrorWidget

See the source code of the ErrorWidget. Just to create a Widget, where is the ErrorWidget displayed? There are three code calls to the ErrorWidget, all of which have one thing in common. If an exception occurs during the build Widget, an ErrorWidget will be returned. The source code is as follows:

  1. ComponentElement (framework. Dart)
@override
  void performRebuild() {
    assert(() {
      if (debugProfileBuildsEnabled)
        Timeline.startSync('${widget.runtimeType}',  arguments: timelineWhitelistArguments);
      return true; } ()); assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(true));
    Widget built;
    try {
      built = build();
      debugWidgetBuilderValue(widget, built);
    } catch (e, stack) {
      built = ErrorWidget.builder(_debugReportException('building $this', e, stack)); } finally { // We delay marking the element as clean until after calling build() so // that attempts to markNeedsBuild()  during build() will be ignored. _dirty =false;
      assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(false)); } try { _child = updateChild(_child, built, slot); assert(_child ! = null); } catch (e, stack) { built = ErrorWidget.builder(_debugReportException('building $this', e, stack));
      _child = updateChild(null, built, slot);
    }

    assert(() {
      if (debugProfileBuildsEnabled)
        Timeline.finishSync();
      return true; } ()); }Copy the code
  1. RenderObjectToWidgetElement (binding. Dart)
  void _rebuild() { try { _child = updateChild(_child, widget.child, _rootChildSlot); assert(_child ! = null); } catch (exception, stack) { final FlutterErrorDetails details = FlutterErrorDetails( exception: exception, stack: stack, library:'widgets library',
        context: 'attaching to the render tree'); FlutterError.reportError(details); final Widget error = ErrorWidget.builder(details); _child = updateChild(null, error, _rootChildSlot); }}Copy the code
  1. _LayoutBuilderElement (layout_builder.dart)
void _layout(BoxConstraints constraints) {
    owner.buildScope(this, () {
      Widget built;
      if(widget.builder ! = null) { try { built = widget.builder(this, constraints); debugWidgetBuilderValue(widget, built); } catch (e, stack) { built = ErrorWidget.builder(_debugReportException('building $widget', e, stack)); } } try { _child = updateChild(_child, built, null); assert(_child ! = null); } catch (e, stack) { built = ErrorWidget.builder(_debugReportException('building $widget', e, stack)); _child = updateChild(null, built, slot); }}); }Copy the code