有关如何在不同 IDE 中查找 DevTools 界面的信息,请查阅DevTools 概述

它是什么?

#

Flutter widget 检查器是一款强大的工具,用于可视化和探索 Flutter widget 树。Flutter 框架使用 widget 作为从控件(如文本、按钮和开关)到布局(如居中、填充、行和列)的核心构建块。检查器可帮助您可视化和探索 Flutter widget 树,并可用于以下目的:

  • 理解现有布局
  • 诊断布局问题

Screenshot of the Flutter inspector window

新的 Flutter 检查器

#

作为 Flutter 3.29 的一部分,新的 Flutter 检查器默认启用。但是,可以通过检查器设置对话框禁用它。

可视化调试布局问题

#

以下是检查器工具栏中可用功能的指南。当空间有限时,图标用作标签的可视化版本。

选择 Widget 模式按钮 选择 Widget 模式:启用此按钮以在设备上选择一个 widget 进行检查。要了解更多信息,请查看检查 Widget

显示实现 Widget 按钮 显示实现 Widget:启用此按钮以在 widget 树中显示实现 widget。要了解更多信息,请查看使用 Widget 树

刷新树图标 刷新树
重新加载当前 widget 信息。
慢速动画图标 慢速动画
将动画运行速度放慢 5 倍,以帮助微调它们。
显示参考线模式图标 显示参考线
叠加参考线以协助解决布局问题。
显示基线图标 显示基线
显示基线,用于对齐文本。可用于检查文本是否对齐。
高亮重绘图标 高亮重绘
显示元素重绘时颜色会变化的边框。有助于发现不必要的重绘。
高亮过大图片图标 高亮过大图片
通过反转颜色和翻转图像来高亮显示使用过多内存的图像。

检查 Widget

#

您可以浏览交互式 widget 树以查看附近的 widget 及其字段值。

要在 widget 树中定位单个 UI 元素,请单击工具栏中的“选择 Widget 模式”按钮。这将使设备上的应用程序进入“widget 选择”模式。单击应用程序 UI 中的任何 widget;这将在应用程序屏幕上选择该 widget,并将 widget 树滚动到相应的节点。再次切换“选择 Widget 模式”按钮以退出 widget 选择模式。

调试布局问题时,要查看的关键字段是 sizeconstraints 字段。约束沿树向下流动,而大小沿树向上流动。有关其工作原理的更多信息,请参阅理解约束

Flutter Widget 树

#

Flutter Widget 树允许您可视化、理解和导航应用程序的 Widget 树。

Image of Flutter inspector with Widget Tree highlighted

使用 Widget 树

#

查看项目中创建的 Widget

#

默认情况下,Flutter Widget 树包含您根项目目录中创建的所有 widget。

widget 的父子关系通过单条垂直线(如果父 widget 只有一个子级)或通过缩进(如果父 widget 有多个子级)表示。

例如,对于 widget 树的以下部分

Image of widget tree section

  • Padding 只有一个子级 Row
  • Row 有三个子级:IconSizedBoxFlexible
  • Flexible 只有一个子级 Column
  • Column 有四个子级:TextTextSizedBoxDivider

查看所有 Widget

#

要改为查看 widget 树中的所有 widget,包括在项目外部创建的 widget,请打开“显示实现 Widget”开关。

实现 widget 以比项目中创建的 widget 更浅的字体显示,从而在视觉上区分它们。它们还隐藏在可折叠组后面,可通过内联展开按钮进行展开。

例如,这里是上面 widget 树的相同部分,显示了实现 widget

Image of widget tree section showing implementation widgets

  • Icon 下面有五个折叠的实现 widget
  • 两个 Text widget 都有 RichText 实现 widget 子级
  • Divider 下面有九个折叠的实现 widget

Flutter Widget 浏览器

#

Flutter Widget 浏览器可帮助您更好地理解被检查的 widget。

Image of Flutter inspector with Widget Explorer highlighted

使用 Widget 浏览器

#

在 Flutter 检查器中,选择一个 widget。Widget 浏览器将显示在窗口的右侧。

根据所选 widget,Widget 浏览器将包含以下一项或多项

  • Widget 属性选项卡
  • Flex 浏览器选项卡
  • 渲染对象选项卡

Widget 属性选项卡

#

Image of widget properties tab

属性选项卡显示您的 widget 布局的迷你视图,包括宽度、高度和填充,以及该 widget 的属性列表。

这些属性包括值是否与属性参数的默认值匹配。

渲染对象选项卡

#

Image of render object tab

渲染对象选项卡显示在所选 Flutter widget 的渲染对象上设置的所有属性。

Flex 浏览器选项卡

#

Image of flex explorer tab

当您选择一个 flex widget(例如,RowColumnFlex)或 flex widget 的直接子级时,flex 浏览器工具将显示在 Widget 浏览器中。

flex 浏览器工具可视化 Flex widget 及其子级的布局方式。该浏览器识别主轴和交叉轴,以及每个轴的当前对齐方式(例如,start、end 和 spaceBetween)。它还显示 flex 系数、flex fit 和布局约束等详细信息。

此外,该浏览器还会显示布局约束违规和渲染溢出错误。违规的布局约束以红色显示,溢出错误以标准“黄胶带”模式呈现,就像您在运行设备上看到的那样。这些可视化旨在提高对溢出错误发生原因以及如何修复它们的理解。

The flex explorer showing errors and device inspector

在 flex 浏览器中单击一个 widget 会在设备上的检查器中镜像该选择。“选择 Widget 模式”需要启用此功能。要启用它,请单击检查器中的“选择 Widget 模式”按钮。

The Select Widget Mode button in the inspector

对于某些属性,如 flex 系数、flex fit 和对齐方式,您可以通过浏览器中的下拉列表修改其值。修改 widget 属性时,您不仅会在 flex 浏览器中看到新值反映出来,而且在运行 Flutter 应用程序的设备上也会看到。浏览器会在属性更改时进行动画显示,以便更改的效果清晰可见。从布局浏览器进行的 widget 属性更改不会修改您的源代码,并在热重载时还原。

交互式属性
#

flex 浏览器支持修改 mainAxisAlignmentcrossAxisAlignmentFlexParentData.flex。将来,我们可能会增加对其他属性的支持,例如 mainAxisSizetextDirectionFlexParentData.fit

mainAxisAlignment
#

The flex explorer changing main axis alignment

支持的值

  • MainAxisAlignment.start
  • MainAxisAlignment.end
  • MainAxisAlignment.center
  • MainAxisAlignment.spaceBetween
  • MainAxisAlignment.spaceAround
  • MainAxisAlignment.spaceEvenly
crossAxisAlignment
#

The flex explorer changing cross axis alignment

支持的值

  • CrossAxisAlignment.start
  • CrossAxisAlignment.center
  • CrossAxisAlignment.end
  • CrossAxisAlignment.stretch
FlexParentData.flex
#

The flex explorer changing flex factor

flex 浏览器在 UI 中支持 7 种 flex 选项(null、0、1、2、3、4、5),但从技术上讲,flex widget 子级的 flex 系数可以是任意整数。

Flexible.fit
#

The flex explorer changing fit

flex 浏览器支持两种不同类型的 FlexFitloosetight

可视化调试

#

Flutter 检查器提供了多种选项,用于可视化调试您的应用程序。

Inspector visual debugging options

慢速动画

#

启用后,此选项会将动画运行速度放慢 5 倍,以便于可视化检查。如果您想仔细观察和调整一个看起来不太对劲的动画,这会很有用。

这也可以在代码中设置

dart
import 'package:flutter/scheduler.dart';

void setSlowAnimations() {
  timeDilation = 5.0;
}

这将动画速度降低 5 倍。

另请参阅

#

以下链接提供了更多信息。

以下屏幕录像显示了动画放慢前后的效果。

Screen recording showing normal animation speed Screen recording showing slowed animation speed

显示参考线

#

此功能会在您的应用程序上绘制参考线,显示渲染框、对齐、填充、滚动视图、剪裁和间隔符。

此工具可用于更好地理解您的布局。例如,通过查找不需要的填充或理解 widget 对齐方式。

您也可以在代码中启用此功能

dart
import 'package:flutter/rendering.dart';

void showLayoutGuidelines() {
  debugPaintSizeEnabled = true;
}

渲染框

#

在屏幕上绘制的 widget 会创建一个渲染框,这是 Flutter 布局的构建块。它们以亮蓝色边框显示

Screenshot of render box guidelines

对齐

#

对齐以黄色箭头显示。这些箭头显示 widget 相对于其父级的垂直和水平偏移。例如,此按钮的图标显示为由四个箭头居中

Screenshot of alignment guidelines

填充

#

填充以半透明蓝色背景显示

Screenshot of padding guidelines

滚动视图

#

具有滚动内容的 widget(如列表视图)以绿色箭头显示

Screenshot of scroll view guidelines

剪裁

#

剪裁(例如使用 ClipRect widget 时)以带剪刀图标的粉色虚线显示

Screenshot of clip guidelines

间隔符

#

间隔符 widget 以灰色背景显示,例如这个没有子级的 SizedBox

Screenshot of spacer guidelines

显示基线

#

此选项使所有基线可见。基线是用于定位文本的水平线。

这对于检查文本是否精确垂直对齐很有用。例如,以下截图中文字基线略微未对齐

Screenshot with show baselines enabled

Baseline widget 可用于调整基线。

在任何设置了基线的渲染框上都会绘制一条线;字母基线显示为绿色,表意基线显示为黄色。

您也可以在代码中启用此功能

dart
import 'package:flutter/rendering.dart';

void showBaselines() {
  debugPaintBaselinesEnabled = true;
}

高亮重绘

#

此选项会在所有渲染框周围绘制一个边框,该边框在每次框重绘时都会改变颜色。

这种旋转的彩虹色有助于发现应用程序中重绘过于频繁并可能损害性能的部分。

例如,一个小的动画可能会导致整个页面在每一帧都重绘。将动画包装在 RepaintBoundary widget 中可将重绘限制为仅动画部分。

此处进度指示器导致其容器重绘

dart
class EverythingRepaintsPage extends StatelessWidget {
  const EverythingRepaintsPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Repaint Example')),
      body: const Center(child: CircularProgressIndicator()),
    );
  }
}

Screen recording of a whole screen repainting

将进度指示器包装在 RepaintBoundary 中只会导致屏幕的该部分重绘

dart
class AreaRepaintsPage extends StatelessWidget {
  const AreaRepaintsPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Repaint Example')),
      body: const Center(
        child: RepaintBoundary(child: CircularProgressIndicator()),
      ),
    );
  }
}

Screen recording of a just a progress indicator repainting

RepaintBoundary widget 有其权衡之处。它们可以帮助提高性能,但也会产生创建新画布的开销,这会占用额外的内存。

您也可以在代码中启用此选项

dart
import 'package:flutter/rendering.dart';

void highlightRepaints() {
  debugRepaintRainbowEnabled = true;
}

高亮过大图片

#

此选项通过反转图像颜色和垂直翻转图像来高亮显示过大的图像

A highlighted oversized image

高亮显示的图像使用了比所需更多的内存;例如,一张 5MB 的大图显示为 100 乘 100 像素。

此类图像可能导致性能不佳,尤其是在低端设备上,当您有许多图像时(例如在列表视图中),这种性能损失会累积。每张图像的信息都会打印在调试控制台中

dash.png has a display size of 213×392 but a decode size of 2130×392, which uses an additional 2542KB.

如果图像使用的内存比所需内存多至少 128KB,则认为它们过大。

修复图像

#

在可能的情况下,解决此问题的最佳方法是调整图像资产文件的大小,使其更小。

如果无法做到这一点,您可以使用 Image 构造函数上的 cacheHeightcacheWidth 参数

dart
class ResizedImage extends StatelessWidget {
  const ResizedImage({super.key});

  @override
  Widget build(BuildContext context) {
    return Image.asset('dash.png', cacheHeight: 213, cacheWidth: 392);
  }
}

这会使引擎以指定大小解码此图像,并减少内存使用(解码和存储仍然比图像资产本身缩小更昂贵)。无论这些参数如何,图像都会根据布局或宽度和高度的约束进行渲染。

此属性也可以在代码中设置

dart
void showOversizedImages() {
  debugInvertOversizedImages = true;
}

更多信息

#

您可以从以下链接了解更多信息

跟踪 Widget 创建

#

Flutter 检查器的一部分功能基于对应用程序代码进行插桩,以便更好地理解 widget 创建的源位置。源插桩允许 Flutter 检查器以与 UI 在源代码中定义方式类似的方式呈现 widget 树。没有它,widget 树中的节点树会深得多,并且可能更难理解运行时 widget 层次结构如何与应用程序的 UI 对应。

您可以通过将 --no-track-widget-creation 传递给 flutter run 命令来禁用此功能。

以下是启用和禁用跟踪 widget 创建时 widget 树可能看起来的样子示例。

跟踪 widget 创建已启用(默认)

The widget tree with track widget creation enabled

跟踪 widget 创建已禁用(不推荐)

The widget tree with track widget creation disabled

此功能可防止在调试版本中将原本相同的 const Widget 视为相等。有关更多详细信息,请参阅关于调试时的常见问题讨论。

检查器设置

#

The Flutter Inspector Settings dialog

启用悬停检查

#

将鼠标悬停在任何 widget 上都会显示其属性和值。

切换此值可启用或禁用悬停检查功能。

启用 Widget 树自动刷新

#

启用后,widget 树会在热重载或导航事件后自动刷新。

使用旧版检查器

#

启用后,使用旧版检查器而不是新检查器。

包目录

#

默认情况下,DevTools 将 widget 树中显示的 widget 限制为在项目根目录中创建的那些。要查看所有 widget,包括在项目根目录之外创建的 widget,请打开“显示实现 Widget”开关

为了在默认 widget 树中包含其他 widget,必须将其父目录添加到包目录中。

例如,考虑以下目录结构

project_foo
  pkgs
    project_foo_app
    widgets_A
    widgets_B

project_foo_app 运行您的应用程序时,在 widget 检查器树中仅显示来自 project_foo/pkgs/project_foo_app 的 widget。

要在 widget 树中显示来自 widgets_A 的 widget,请将 project_foo/pkgs/widgets_A 添加到包目录中。

要在 widget 树中显示来自项目根目录的所有 widget,请将 project_foo 添加到包目录中。

对包目录的更改在下次为应用程序打开 widget 检查器时将保持不变。

其他资源

#

有关检查器通常可以实现的功能的演示,请观看DartConf 2018 演讲,其中演示了 IntelliJ 版本的 Flutter 检查器。

要了解如何使用 DevTools 可视化调试布局问题,请查看 Flutter 检查器指导教程