当前位置:首页 > 科技  > 软件

了解并解决 Flutter 中的灰屏问题

来源: 责编: 时间:2024-06-14 08:51:14 220观看
导读生产中的 flutter 应用程序中的灰屏是一种通用占位符,当框架遇到问题无法渲染预期用户界面时就会显示。是的,所以基本上是出现问题时的后备指示器。有趣的是,这只出现在发布模式下。在任何其他模式下运行都会显示红色错

生产中的 flutter 应用程序中的灰屏是一种通用占位符,当框架遇到问题无法渲染预期用户界面时就会显示。是的,所以基本上是出现问题时的后备指示器。O6V28资讯网——每日最新资讯28at.com

有趣的是,这只出现在发布模式下。在任何其他模式下运行都会显示红色错误屏幕,并说明导致错误的原因。(检查此处以了解各种类型的构建模式。)此类错误的常见原因是:O6V28资讯网——每日最新资讯28at.com

  • 未处理的异常:这些是运行时发生的错误,未使用 try-catch 块捕获。
  • 渲染错误:这些是渲染布局时引起的问题,例如,在 Column 、 Row 或 Flex 小部件外部使用 Expanded 时引起的问题。

以下是可能导致灰屏的代码示例:O6V28资讯网——每日最新资讯28at.com

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 运算符(!),这导致在非发布模式下出现红屏,在发布模式下出现灰屏。O6V28资讯网——每日最新资讯28at.com

需要注意的是,我们不建议在不更新的情况下将部件明确设置为空值,空值错误是一个常见错误,而上述操作是重现该错误的简单方法。O6V28资讯网——每日最新资讯28at.com

图片图片O6V28资讯网——每日最新资讯28at.com

调试模式下的红色错误屏幕(左)和发布模式下的灰色屏幕(右)的图像调试模式下的红色错误屏幕(左)和发布模式下的灰色屏幕(右)的图像O6V28资讯网——每日最新资讯28at.com

自定义错误屏幕

为了显示更用户友好的消息而不是灰屏,我们将策略性地在 main 函数中放置一行代码。该行充当预防措施,确保每当发生未处理的异常时都会显示自定义错误屏幕。O6V28资讯网——每日最新资讯28at.com

void main() {  ErrorWidget.builder = (_) => const AppErrorWidget(); // This line does the magic!  runApp(MyApp());}

有条件的红屏(可选):

也许您希望在开发过程中看到默认的红色错误屏幕以进行调试。您可以通过将 ErrorWidget.builder 赋值包装在检查当前构建模式的 if 语句中来实现此目的:O6V28资讯网——每日最新资讯28at.com

void main() {  if (kReleaseMode) ErrorWidget.builder = (_) => const AppErrorWidget();  runApp(MyApp());}

下一步涉及创建 AppErrorWidget 本身的内容。该小部件将确定发生未处理的异常时用户看到的内容。O6V28资讯网——每日最新资讯28at.com

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,              style: TextStyle(                fontSize: 16,              ),            ),          ],        ),      ),    );  }}

AppErrorWidget 小部件的结果显示AppErrorWidget 小部件的结果显示O6V28资讯网——每日最新资讯28at.com

虽然鼓励自定义应用程序的体验,但 ErrorWidget.builder 上的 Flutter 文档提醒我们,调用错误小部件时视图处于不稳定状态。构建(可能还有布局)期间的异常会使系统处于脆弱状态。为了最大限度地减少进一步的问题,返回的小部件应该做最少的工作。LeafRenderObjectWidget (如默认的 RenderErrorBox )非常适合处理意外约束。O6V28资讯网——每日最新资讯28at.com

ErrorWidget.builder 的幕后花絮

现在我们知道,当渲染预期 UI 的过程中发生错误时, ErrorWidget.builder 就会被调用,但是这到底是如何实现的呢?O6V28资讯网——每日最新资讯28at.com

如果我们深入研究 Flutter 的框架,我们会在构建或重建小部件时看到一个名为 _updateChild() 的方法。O6V28资讯网——每日最新资讯28at.com

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 变量以显示自定义错误小部件而不是原始子小部件。O6V28资讯网——每日最新资讯28at.com

提升开发者体验

定制向用户呈现错误的方式是改善用户体验的关键一步。虽然 ErrorWidget.builder 帮助我们在出现错误时管理用户体验,但它并没有为生产环境中的开发人员提供有价值的见解。本地调试不再是一种选择,那么我们如何及时了解用户设备上发生的错误呢?O6V28资讯网——每日最新资讯28at.com

这就是我们利用 FlutterError.onError 回调的力量的地方。让我们看看这是如何完成的:O6V28资讯网——每日最新资讯28at.com

void main() {  if (kReleaseMode) ErrorWidget.builder = (_) => const AppErrorWidget();  FlutterError.onError = (details) {    FlutterError.dumpErrorToConsole(details);    if (!kReleaseMode) return;    // 发送到您的 crashlytics 服务...  };  runApp(MyApp());}

我们添加了一行新代码,它将新的回调函数分配给 FlutterError.onError 属性。每当使用 FlutterError.reportError 报告错误时都会调用此回调。O6V28资讯网——每日最新资讯28at.com

在回调内部, FlutterError.dumpErrorToConsole(details) 通过将错误详细信息转储到控制台来帮助我们了解幕后情况。这对于在部署或分阶段部署期间可能存在对用户设备的访问受限的调试目的非常有用。O6V28资讯网——每日最新资讯28at.com

最后的注释行 ( // 发送到您的 crashlytics 服务... ) 强调了这种方法的真正威力。在这里,您可以集成您选择的错误报告服务(例如 Crashlytics)以发送详细的错误报告以供分析。O6V28资讯网——每日最新资讯28at.com

注意:此行包含在 if 语句中,以确保它仅在调试或分析模式下执行 ( !kReleaseMode )。O6V28资讯网——每日最新资讯28at.com

避免灰屏的最佳错误处理实践

我们已经了解了导致灰屏的原因以及出现灰屏时如何更好地处理它;我们还应该介绍的一件事是,作为开发人员可以采取哪些措施来避免出现灰屏。其中一些是:O6V28资讯网——每日最新资讯28at.com

  • 拥抱 try-catch :将关键代码部分包装在 try-catch 块内。这允许您捕获潜在的异常并提供优雅的回退机制。
  • **少用 Bang 运算符 (!)**:bang 运算符 (!) 是 null 断言检查的快捷方式,但如果用于不确定是否为非 null 的值,可能会导致意外错误。更多地使用条件表达式 (??) 或 null 感知访问运算符 (?.)。
  • 彻底的应用程序测试:结合使用单元、小部件、集成和手动测试来帮助在问题出现在生产中之前识别和解决问题。
  • 尊重 Widget 约束:Flutter 中的每个 Widget 都有局限性和预期的使用模式;避免在其限制之外使用它们,例如在可滚动视图中使用 Spacer 。

结论:拥抱不可避免的事情

错误处理是任何编写良好的 Flutter 应用程序的重要组成部分。当您努力编写干净的代码并预测潜在问题时,异常情况必然会发生。通过实施 ErrorWidget.builder ,您可以确保即使发生意外情况,您的用户也会看到清晰且内容丰富的消息,而不是令人困惑的灰屏,并且通过 FlutterError.onError 您可以确保您记录这些意外错误,并且可以更轻松地调试和修复这些错误。O6V28资讯网——每日最新资讯28at.com

请记住,即使面对不可预见的障碍,一点准备对于保持积极的用户和开发人员体验也大有帮助。O6V28资讯网——每日最新资讯28at.com

原文:https://medium.com/@LordChris/understanding-and-addressing-the-grey-screen-in-flutter-5e72c31f408fO6V28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-93688-0.html了解并解决 Flutter 中的灰屏问题

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 生成式人工智能是 DevSecOps 的福音还是噩梦?

下一篇: 为什么很多人用Java好几年,还是不太理解泛型?

标签:
  • 热门焦点
  • 7月安卓手机性价比榜:努比亚+红魔两款新机入榜

    7月登场的新机有努比亚Z50S Pro和红魔8S Pro,除了三星之外目前唯二的两款搭载超频版骁龙8Gen2处理器的产品,而且努比亚和红魔也一贯有着不错的性价比,所以在本次的性价比榜单
  • 6月安卓手机性价比榜:Note 12 Turbo断层式碾压

    6月份有一个618,虽然这是京东周年庆的日子,但别的电商也都不约而同的跟进了,反正促销没坏处,厂商和用户都能满意。618期间一些产品也出现了历史低价,那么各个价位段的产品性价比
  • 线程通讯的三种方法!通俗易懂

    线程通信是指多个线程之间通过某种机制进行协调和交互,例如,线程等待和通知机制就是线程通讯的主要手段之一。 在 Java 中,线程等待和通知的实现手段有以下几种方式:Object 类下
  • 微信语音大揭秘:为什么禁止转发?

    大家好,我是你们的小米。今天,我要和大家聊一个有趣的话题:为什么微信语音不可以转发?这是一个我们经常在日常使用中遇到的问题,也是一个让很多人好奇的问题。让我们一起来揭开这
  • 19个 JavaScript 单行代码技巧,让你看起来像个专业人士

    今天这篇文章跟大家分享18个JS单行代码,你只需花几分钟时间,即可帮助您了解一些您可能不知道的 JS 知识,如果您已经知道了,就当作复习一下,古人云,温故而知新嘛。现在,我们就开始今
  • 破圈是B站头上的紧箍咒

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之每年的暑期档都少不了瞄准追剧女孩们的古偶剧集,2021年有优酷的《山河令》,2022年有爱奇艺的《苍兰诀》,今年却轮到小破站抓住了追
  • 阿里瓴羊One推出背后,零售企业迎数字化新解

    作者:刘旷近年来随着数字经济的高速发展,各式各样的SaaS应用服务更是层出不穷,但本质上SaaS大多局限于单一业务流层面,对用户核心关切的增长问题等则没有提供更好的解法。在Saa
  • 2299元起!iQOO Pad开启预售:性能最强天玑平板

    5月23日,iQOO如期举行了新品发布会,除了首发安卓最强旗舰处理器的iQOO Neo8系列新机外,还在发布会上推出了旗下首款平板电脑——iQOO Pad,其搭载了天玑
  • 回归OPPO两年,一加赢了销量,输了品牌

    成为OPPO旗下主打性能的先锋品牌后,一加屡创佳绩。今年618期间,一加手机全渠道销量同比增长362%,凭借一加 11、一加 Ace 2、一加 Ace 2V三款爆品,一加
Top