教你如何自定义Flutter错误页面

栏目: IOS · Android · 发布时间: 7年前

内容简介:开发Flutter的时候,肯定都会遇到Flutter错误页面,可以让我们在开发的时候很清楚的知道代码有异常,但是,如果发布出去的APP出现了异常,那么这个错误页面就很不友好,其实这个错误页面是可以自定义的,本篇文章告诉你如何自定义错误页面!这是我们经常看到的错误页面:要想Flutter的错误页面显示成自定义的页面,只要设置

开发Flutter的时候,肯定都会遇到Flutter错误页面,可以让我们在开发的时候很清楚的知道代码有异常,但是,如果发布出去的APP出现了异常,那么这个错误页面就很不友好,其实这个错误页面是可以自定义的,本篇文章告诉你如何自定义错误页面!

0x01 Flutter错误页面

这是我们经常看到的错误页面:

教你如何自定义Flutter错误页面

0x02 自定义Flutter错误页面

要想Flutter的错误页面显示成自定义的页面,只要设置 ErrorWidgetbuilder 就行。 代码如下:

ErrorWidget.builder = (FlutterErrorDetails flutterErrorDetails){
        print(flutterErrorDetails.toString());
        return Center(
          child: Text("Flutter 走神了"),
          );
    };
复制代码

ErrorWidget.builder 返回一个Widget,当Flutter出错的时候就会显示这个Widget, 下图就是我们自定义的错误页面,比Flutter的友好多了:

教你如何自定义Flutter错误页面

0x03 github

本篇文章所涉及的代码: github.com/koudle/GDG_…

github地址: github.com/koudle/GDG_…

0x04 ErrorWidget源码分析

ErrorWidget 的源码在 framework.dart 的3581行-3630行,很简单, ErrorWidget 的构造函数的参数是exception的对象,然后返回一个内容是exception message信息的RenderBox,我们看到的Flutter的错误页面就是这个RenderBox。

class ErrorWidget extends LeafRenderObjectWidget {
  /// 创建一个显示error message的Widget,exception是构造函数的参数。
  ErrorWidget(Object exception) : message = _stringify(exception),
      super(key: UniqueKey());

  //ErrorWidgetBuilder.builder的默认设置是ErrorWidget,我们可以设置成自己的
  static ErrorWidgetBuilder builder = (FlutterErrorDetails details) => ErrorWidget(details.exception);

  /// The message to display.
  final String message;

  //将exception对象转换成string
  static String _stringify(Object exception) {
    try {
      return exception.toString();
    } catch (e) { } // ignore: empty_catches
    return 'Error';
  }
  
  //返回一个内容是exception message信息的RenderBox
  @override
  RenderBox createRenderObject(BuildContext context) => RenderErrorBox(message);

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('message', message, quoted: false));
  }
}
复制代码

0x05 调用ErrorWidget的源码分析

前面看了 ErrorWidget 的源码,只是创建一个Widget,那么是哪里调用 ErrorWidget 显示的呢? 调用 ErrorWidget 的代码总共有三处,这三处都有一个共同点,就是在build Widget的过程中,如果出现异常,则返回一个ErrorWidget显示,具体的源码如下:

  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;
    }());
  }
复制代码
  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);
    }
  }
复制代码
  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);
      }
    });
  }
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Ant Colony Optimization

Ant Colony Optimization

Marco Dorigo、Thomas Stützle / A Bradford Book / 2004-6-4 / USD 45.00

The complex social behaviors of ants have been much studied by science, and computer scientists are now finding that these behavior patterns can provide models for solving difficult combinatorial opti......一起来看看 《Ant Colony Optimization》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具