class HomeView extends HookWidget { const HomeView({super.key}); @override Widget build(BuildContext context) { const widget = null; return Scaffold( appBar: AppBar( title: Text( 'Gallery', style: Theme.of(context).textTheme.headlineLarge, ), ), body: widget!, ); } }在这里,我们犯了一个明显的错误,在我们知道的 null 小部件上使用了 bang 运算符(!),这导致在非发布模式下出现红屏,在发布模式下出现灰屏。需要注意的是,我们不建议在不更新的情况下将部件明确设置为空值,空值错误是一个常见错误,而上述操作是重现该错误的简单方法。
调试模式下的红色错误屏幕(左)和发布模式下的灰色屏幕(右)的图像
void main() { ErrorWidget.builder = (_) => const AppErrorWidget(); // This line does the magic! runApp(MyApp()); }有条件的红屏(可选):
void main() { if (kReleaseMode) ErrorWidget.builder = (_) => const AppErrorWidget(); runApp(MyApp()); }下一步涉及创建 AppErrorWidget 本身的内容。该小部件将确定发生未处理的异常时用户看到的内容。
class AppErrorWidget extends StatelessWidget { const AppErrorWidget({super.key}); @override Widget build(BuildContext context) { return const Material( color: Colors.white, child: Padding( padding: EdgeInsets.all(24), child: Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.warning, size: 200, color: Colors.amber, ), SizedBox(height: 48), Text( 'So... something funny happened', textAlign: TextAlign.center, style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), SizedBox(height: 16), Text( 'This error is crazy large it covers your whole screen. But no worries' ' though, we\'re working to fix it.', textAlign: TextAlign.center,// 堆代码 duidaima.com style: TextStyle( fontSize: 16, ), ), ], ), ), ); } }
void _updateChild() { try { final Widget child = (widget as _RawView).builder(this, _effectivePipelineOwner); _child = updateChild(_child, child, null); } catch (e, stack) { final FlutterErrorDetails details = FlutterErrorDetails( exception: e, stack: stack, library: 'widgets library', context: ErrorDescription('building $this'), informationCollector: !kDebugMode ? null : () => <DiagnosticsNode>[ DiagnosticsDebugCreator(DebugCreator(this)), ], ); FlutterError.reportError(details); final Widget error = ErrorWidget.builder(details); _child = updateChild(null, error, slot); } }我们可以看到 ErrorWidget.builder 属性用于根据提供的 FlutterErrorDetails 检索自定义错误小部件;然后更新 _child 变量以显示自定义错误小部件而不是原始子小部件。
void main() { if (kReleaseMode) ErrorWidget.builder = (_) => const AppErrorWidget(); FlutterError.onError = (details) { FlutterError.dumpErrorToConsole(details); if (!kReleaseMode) return; // 发送到您的 crashlytics 服务... }; runApp(MyApp()); }我们添加了一行新代码,它将新的回调函数分配给 FlutterError.onError 属性。每当使用 FlutterError.reportError 报告错误时都会调用此回调。在回调内部, FlutterError.dumpErrorToConsole(details) 通过将错误详细信息转储到控制台来帮助我们了解幕后情况。这对于在部署或分阶段部署期间可能存在对用户设备的访问受限的调试目的非常有用。
尊重 Widget 约束:Flutter 中的每个 Widget 都有局限性和预期的使用模式;避免在其限制之外使用它们,例如在可滚动视图中使用 Spacer 。