内容简介:开发Flutter的时候,肯定都会遇到Flutter错误页面,可以让我们在开发的时候很清楚的知道代码有异常,但是,如果发布出去的APP出现了异常,那么这个错误页面就很不友好,其实这个错误页面是可以自定义的,本篇文章告诉你如何自定义错误页面!这是我们经常看到的错误页面:要想Flutter的错误页面显示成自定义的页面,只要设置
开发Flutter的时候,肯定都会遇到Flutter错误页面,可以让我们在开发的时候很清楚的知道代码有异常,但是,如果发布出去的APP出现了异常,那么这个错误页面就很不友好,其实这个错误页面是可以自定义的,本篇文章告诉你如何自定义错误页面!
0x01 Flutter错误页面
这是我们经常看到的错误页面:
0x02 自定义Flutter错误页面
要想Flutter的错误页面显示成自定义的页面,只要设置 ErrorWidget
的 builder
就行。 代码如下:
ErrorWidget.builder = (FlutterErrorDetails flutterErrorDetails){ print(flutterErrorDetails.toString()); return Center( child: Text("Flutter 走神了"), ); }; 复制代码
ErrorWidget.builder
返回一个Widget,当Flutter出错的时候就会显示这个Widget, 下图就是我们自定义的错误页面,比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显示,具体的源码如下:
- 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; }()); } 复制代码
- 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); } } 复制代码
- _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); } }); } 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 自定义错误上报的奇怪问题
- Django 自定义 404 500 等错误页面
- knockout.js – 自定义错误消息和位置
- sql-server-2005 – 如何在SSIS包中创建错误日志或自定义错误日志?
- ES5 / ES6 自定义错误类型比较
- Laravel Validator 自定义错误返回提示消息以及前端展示
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。