第22章 改进 Flutter 的错误提示信息
提升 Flutter 错误提示的体验
视觉设计真的能用在错误信息上吗?我们发现,这样做能大幅提升 Flutter 错误信息的好用程度。
Tao Dong 2019年9月9日 · 8 分钟阅读
rss_feed
分享到 X 分享到 Bluesky 分享到 LinkedIn
当你编写计算机程序时,即使是最经验丰富的开发者也难免会引入错误。解决错误的第一步,通常是阅读控制台里打印出来的错误信息。但研究表明,程序员——尤其是新手——往往很难看懂这些错误信息,更别提根据提示去解决问题了。
说实话,在帮开发者从错误中恢复这件事上,Flutter 做得并不够好。错误的控制台输出通常冗长,而且常常很难把错误追溯到代码中的具体位置。最近,我们一直在着手解决这两个问题。在这篇文章里,我会介绍我们首次尝试提升 Flutter 运行时错误信息信噪比的工作,并说明我们为了得出当前方案所做的研究。
引入结构化错误信息
在 IntelliJ/Android Studio 的 Flutter 插件和 VS Code 扩展的最新版本中,我们上线了一个新功能,能以丰富而简洁的格式显示错误信息。日志控制台现在展示错误信息时,会有以下改进:
- 用红色高亮错误摘要 - 在各区块之间添加留白,让信息更容易扫读 - 如果错误提示中包含解决建议,就单独强调出来 - 折叠信息中较长的列表和树形结构
下面这张截图展示了由布局溢出错误生成的信息中,用蓝色圆圈标出的四处改进:
一种新的结构化错误信息示例
注意,所有内容都能在一屏内放下,让你一眼就能对问题有个大概了解。减少信息噪音并没有删掉任何可能对修复错误有帮助的细节。
相比之下,原来的错误信息更密集、缺少结构,很难找到告诉你怎么修的信息。看下面这张截图。
同一个 RenderFlex Overflow 错误的原始信息
目前,我们重构了 Flutter 框架中约 85% 的错误信息,以利用这种新的展示方式。其余错误信息的改进会逐步完成。我们还计划根据用户反馈来优化错误信息的整体呈现。
我们是怎么走到这一步的?
错误信息的好用程度是个多维度问题。错误信息的内容、结构和呈现方式都影响着你能否看懂问题并修复它。我们知道 Flutter 的错误信息通常内容是有用的,但海量信息会削弱这些内容的价值。
举个例子,看看 “No Material widget found” 这个错误。当一个 widget 在其祖先树中期待一个 Material widget 但没找到时,就会触发这个错误。这个错误的信息太难理解了,以至于有用户去 StackOverflow 求助。被采纳的回答指出了错误信息里已经包含的关键信息,但这位用户要么没找到,要么没看懂。回答里也没有提供任何新信息。
一个关于 “No Material widget found” 错误发到 StackOverflow 上的问题
错误信息的新展示方式
StackOverflow 上的那个问题很有启发。它说明错误信息里的信息并非同等重要。这也促使我们去思考怎么让有用的信息更醒目,也就是要减少视觉干扰。应用视觉感知理论和 UX 设计手法,我们为这个错误信息设计了三个版本:颜色、留白和省略。
为了做出颜色版本,我们分析了信息中各部分的重要性,得出了一个简单的配色方案:
- 用红色显示一行的错误摘要。 - 用蓝色显示与错误相关的对象。 - 用灰色显示通常不需要的细节。
“Missing Material” 错误信息的颜色版本
下一个版本叫留白版本。我们在错误信息中加了留白,把它分成不同区块,还加了 Explanation、Potential Fix 这类区块标题,让信息更好扫读。
“Missing Material” 错误信息的留白版本
最后,省略版本在错误信息展示中运用了渐进式披露技术,并借助了现代 IDE 的能力。比如,我们折叠了 TextField widget 的参数列表,只显示前三个;widget 的祖先也一样,只显示前三个。想看完整列表,点击最后一个参数或祖先后面的省略号就行。生成的错误信息比原来短很多,让你更有可能一眼注意到信息中的高层级元素。
“Missing Material” 错误信息的省略版本
我们有充分理由相信这些版本能帮到用户,但还不确定实现它们值得花那么多代价。要让这些呈现方式变成现实,需要让 Flutter 框架向 IDE 发送结构化错误数据,这样 IDE 才能给不同部分(比如摘要、细节、提示)加上不同样式,并折叠不那么重要的信息。我们问了自己:改善开发者体验的潜在好处,值不值得为此重构 Flutter 的错误 API 以及已经写好的上百个错误。于是我们决定做个实验,看看结构化错误信息到底能带来多大收益。
实验
为了比较三个版本和原始信息在可用性上的差异,我们做了一项基于场景问卷的在线实验。我们找了 52 名 Flutter 用户,随机把他们分到四个实验组。对照组看到的是原始错误信息,另外三个处理组分别看到三种版本。参与者需要在很短的时间窗口内描述出出了什么问题以及他们会怎么解决。详细的研究设计见我们今年早些时候在 CHI 2019 上发表的同行评审论文。
四种信息版本下的错误理解率
结果让我们非常惊喜。三个处理组对错误信息的理解明显好于对照组。换句话说,当用任何一个版本代替原始信息时,能在时限内正确理解错误的参与者比例要高得多。下面这张图显示,当给参与者总共 45 秒阅读错误信息时,留白版本比原始格式的理解率高出约 38 个百分点。
四种信息版本下的错误修复率
同样,在寻找解决方案时,所有版本的错误信息表现都优于原始的呈现方式。
当参与者被要求比较原始错误信息和他们在实验中使用的版本时,他们解释了自己为什么更喜欢版本化的信息。下面是一些例子(括号里的词是本文作者补上的)。
“右边的错误信息(颜色版本)有了巨大提升,红色的短摘要指出了关键信息,蓝色的 widget 标出了受影响的部分。” “把整个 Widget 对象藏起来(省略版本)减少了杂乱,很容易找到错误发生的原因。” “B(留白版本)好读多了。区块分得很清楚,扫读时很容易知道接下来该跳去哪。”
有了实验提供的有力证据,我们决定投入资源做结构化错误信息。这是一段漫长的旅程,但很高兴看到重构后的错误 API 现在为未来的创新打下了坚实的基础,帮助开发者在他们自己的 Flutter 项目里从错误中恢复。
错误信息的未来是什么?
对于由 UI 代码抛出的错误,我们可以在信息里嵌入图表、动画甚至可交互的 widget 树,最大化它们的解释力。我们计划先在 Dart DevTools 的控制台里开始一些更大胆的实验,因为我们不受 IntelliJ 和 VS Code 扩展性的限制。
你能为我们做什么?
不是所有 Flutter 错误都做了重构,以充分利用这种新的结构化呈现。我们在优先处理影响最多 Flutter 用户的错误。你可以通过我们的 GitHub issue 跟踪器告诉我们哪些错误信息可以更有用,也可以提出关于在 IntelliJ 或 VS Code 里优化错误呈现的想法。
致谢
Flutter 团队前 UX 研究实习生 Kandarp Khandwala 为本文描述的研究做出了关键贡献。我们也感谢所有参与实验的 Flutter 用户。
Flutter 更多内容
我如何把 GenLatte 改成全栈 Dart 以及降低了 App 的服务器账单
Craig Labenz
2026年9月22日 · 7 分钟阅读
用 A2UI 的客户端函数做快速、可靠的计算
了解客户端函数如何让 agent 直接把本地操作委托给跑在用户设备上的 Dart 代码。
Andrew Brogdon
2026年8月28日 · 5 分钟阅读