调试 Flutter 应用

有很多工具和特性可以帮助调试 Flutter 应用程序,如下列举了一些:

  • 开发者工具,是一套运行在浏览器的性能及分析工具。

  • Android Studio/IntelliJVS Code(借助 Flutter 和 Dart 插件)支持内置的源代码调试器,可以设置断点,单步调试,检查数值。

  • Flutter inspector,是开发者工具提供的 widget 检查器,也可直接在 Android Studio 和 IntelliJ 中使用(借助 Flutter 插件)。检查器可以可视化展现 widget 树,查看单个 widget 及其属性值,开启性能图层,等等。

开发者工具

要调试及分析应用,开发者工具可能是你的首选。开发者工具运行在浏览器,支持以下特性:

  • 源代码调试器

  • widget 检查器,展示可视化的 widget 树;“widget select” 模式,在应用中选择一个 widget,会在 widget 树直接定位到它的位置。

  • 内存分析

  • 时间线视图,支持跟踪,导入及导出跟踪信息

  • 日志视图

如果你在 debug 模式profile 模式 运行,那么可以在浏览器打开开发者工具连接到你的应用。开发者工具不能用在以 release 模式 编译的应用,因为调试和分析信息都被删除了。

如果你要用开发者工具分析应用,需确保使用 profile 模式。否则,分析的主要输出将会是用于验证框架中各种不变式的调试断言(查看 debug 模式断言)。

展示开发者工具特性的 GIF

想获取更多信息,请查看 开发者工具 文档。

设置断点

要设置断点,可以直接在 IDE 或编辑器(比如 Android Studio/IntelliJVS Code)、开发者工具调试器 设置,或者 通过编码的方式设置

Dart 分析器

如果你使用的是 Flutter 推荐的 IDE 或编辑器,则自带的 Dart 分析器默认会检查代码,并发现可能的错误。

如果你使用命令行,则可以使用 flutter analyze 检查代码。

Dart 分析器非常依赖你在代码中添加的类型注解,以帮助跟踪问题。建议您在各个地方都加上注解(避免 var,无类型参数,无类型 list 字面量,等等),因为这是跟踪问题最快且最不痛苦的方式。

想获取更多信息,请查看 使用 Dart 分析器

日志

另一个有用的调试工具是日志。通过 编码 配置日志,然后在开发者工具中的 日志视图 或控制台查看输出。

调试应用层

Flutter 采用分层架构,包括 widget、渲染和绘制等层。想获取更多信息和视频,请查看 GitHub wiki 上的 The Framework architecture,和社区文章 The Layer Cake

Flutter widget 检查器提供了 widget 树的视觉展现,如果你想要更多细节,或关于 wiget、层级或渲染树的详尽文本转储,请查看 添加输出代码的方式调试 Flutter 应用 页面的 调试标志:应用层 部分。

Debug 模式断言

在开发过程中,强烈建议您使用 Flutter 的 debug 模式。如果你是用 Android Studio 的 bug 图标运行,或者在命令行执行 flutter run,则默认会使用 debug 模式。有些工具通过 —enable-assets 命令行标志可以支持断言语句。

在此模式,Dart 断言语句被开启,Flutter 框架在执行时会计算每一个遇到的断言语句的参数,当结果是 false 时抛出异常。如此一来,开发者可以控制不变式检查的开启或关闭,相应的性能损耗将只发生在调试期间。

有不变式被违反时,它会被报告给控制台,并携带一些帮助跟踪问题源的上下文信息。

想获取更多信息,请查看 探索 Dart 语言 中的 断言 部分。

调试动画

调试动画最简单的方法是让它们变慢。Flutter inspector 提供一个 放慢动画(Slow Animations) 的按钮,你也可以 在代码中放慢动画

想获取更多关于调试动画卡顿的信息,请查看 Flutter 性能分析

Measuring app startup time

测量应用启动时间

要收集有关 Flutter 应用程序启动所需时间的详细信息,可以在运行 flutter run 时使用 trace-startupprofile 选项。

  1. $ flutter run --trace-startup --profile

跟踪输出被保存到 Flutter 工程目录在 build 目录下,一个名为 start_up_info.json 的 JSON 文件中。输出列出了从应用程序启动到这些跟踪事件(以微秒捕获)所用的时间:

  • 进入 Flutter 引擎时

  • 展示应用第一帧时

  • 初始化Flutter框架时

  • 完成Flutter框架初始化时

例如:

  1. {
  2. "engineEnterTimestampMicros": 96025565262,
  3. "timeToFirstFrameMicros": 2171978,
  4. "timeToFrameworkInitMicros": 514585,
  5. "timeAfterFrameworkInitMicros": 1657393
  6. }

Tracing Dart code

跟踪 Dart 代码性能

要进行性能跟踪,你可以使用开发者工具的 时间线视图。时间线视图还支持导入和导出跟踪文件。想要获取更多信息,请查看 时间线视图

你也可以 在代码中跟踪,不过这些跟踪信息无法导入到开发者模式的时间线视图。

跟踪时请确保在 profile 模式 运行应用,这样才能保证运行时性能特征同你最终产品高度一致。

性能图层

要图形化展现你应用的性能,可以开启性能图层。你可以在 Flutter inspector 中点击 Performance Overlay 按钮。

你也可以 在代码中 开启该图层。

关于如何解析图层中的图形,请查看 Flutter 性能分析 中的 性能图层 部分。

调试标志

大部分情况,你不需要直接使用调试标志,因为可以在 开发者工具 找到最有用的调试功能。但是如果你偏好直接使用调试标志,请查看 [添加输出代码的方式调试 Flutter 应用][Debugging Flutter apps programmatically] 中的 调试标志:性能 部分。

常见问题

下面是一些在 macOS 上遇到的问题。

“句柄数超出系统限制” 异常 (macOS)

mac OS 在同一时间可以打开多少句柄的默认限制数相当低。如果你达到这个极限,可以用 ulimit 命令增加可用句柄的数量:

  1. ulimit -S -n 2048

如果您使用 Travis 或 Cirrus 进行测试,请通过在 flutter/.travis.yml 或 flutter/.cirrus.yml 中增加同样的命令来增加它们可以打开的句柄数量。

其他资源

以下是其他一些有用的文档: