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

它是什么?

#

Flutter Widget Inspector 是一个强大的工具,用于可视化和探索 Flutter Widget 树。Flutter 框架使用 Widget 作为核心构建块,用于从控件(如文本、按钮和切换按钮)到布局(如居中、填充、行和列)的各种内容。Inspector 可帮助您可视化和探索 Flutter Widget 树,并可用于以下目的:

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

Screenshot of the Flutter inspector window

新的 Flutter Inspector

#

作为 Flutter 3.29 的一部分,新的 Flutter Inspector 默认启用。但是,您可以从 Inspector 设置对话框 中禁用它。

可视化调试布局问题

#

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

Select widget mode button 选择 Widget 模式:启用此按钮可选择设备上的 Widget 进行检查。了解更多信息,请查看 检查 Widget

Show implementation widgets button 显示实现 Widget:启用此按钮可在 Widget 树中显示实现 Widget。了解更多信息,请查看 使用 Widget 树

Refresh tree icon 刷新树
重新加载当前的 Widget 信息。
Slow animations icon 慢速动画
将动画运行速度放慢 5 倍,以帮助微调它们。
Show guidelines mode icon 显示辅助线
叠加辅助线以帮助修复布局问题。
Show baselines icon 显示基线
显示用于对齐文本的基线。可用于检查文本是否已对齐。
Highlight repaints icon 高亮重绘
显示在元素重绘时会改变颜色的边框。有助于查找不必要的重绘。
Highlight oversized images icon 高亮过大图片
通过反转颜色并翻转它们来高亮显示占用过多内存的图片。

检查 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 Explorer

#

Flutter Widget Explorer 可帮助您更好地理解检查的 Widget。

Image of Flutter inspector with Widget Explorer highlighted

使用 Widget Explorer

#

在 Flutter Inspector 中,选择一个 Widget。Widget Explorer 将显示在窗口的右侧。

根据所选 Widget,Widget Explorer 将包含一个或多个以下项:

  • Widget 属性选项卡
  • Flex Explorer 选项卡
  • Render object 选项卡

Widget 属性选项卡

#

Image of widget properties tab

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

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

Render object 选项卡

#

Image of render object tab

Render object 选项卡显示设置在所选 Flutter Widget 的 render object 上的所有属性。

Flex Explorer 选项卡

#

Image of flex explorer tab

当您选择一个 Flex Widget(例如,RowColumnFlex)或 Flex Widget 的直接子项时,Flex Explorer 工具将出现在 Widget Explorer 中。

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

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

The flex explorer showing errors and device inspector

单击 Flex Explorer 中的 Widget 会镜像在设备上 Inspector 中的选择。为此需要启用 **选择 Widget 模式**。要启用它,请单击 Inspector 中的 **选择 Widget 模式** 按钮。

The Select Widget Mode button in the inspector

对于 flex 因子、flex fit 和对齐等某些属性,您可以通过 Explorer 中的下拉列表修改该值。修改 Widget 属性时,您会看到新值不仅在 Flex Explorer 中反映出来,而且还在运行 Flutter 应用的设备上反映出来。Explorer 在属性更改时进行动画处理,以便更改的效果清晰可见。从布局 Explorer 所做的 Widget 属性更改不会修改您的源代码,并在热重载时恢复。

可交互属性
#

Flex Explorer 支持修改 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 Explorer 在 UI 中支持 7 种 Flex 选项(null、0、1、2、3、4、5),但实际上 Flex Widget 子项的 flex 因子可以是任何整数。

Flexible.fit
#

The flex explorer changing fit

Flex Explorer 支持两种不同类型的 FlexFitloosetight

可视化调试

#

Flutter Inspector 提供了多种可视化调试应用的方法。

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

Padding

#

填充显示为半透明蓝色背景。

Screenshot of padding guidelines

滚动视图

#

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

Screenshot of scroll view guidelines

剪裁

#

剪裁,例如在使用 ClipRect Widget 时,显示为带有剪刀图标的虚线粉色线条。

Screenshot of clip guidelines

间距

#

Spacer 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 的大图片显示为 100x100 像素。

这些图片可能导致性能不佳,尤其是在低端设备上,以及当您有许多图片(如在列表视图中)时,这种性能下降会累加。每张图片的信息都会打印在调试控制台中。

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 Inspector 的部分功能基于对应用程序代码进行插装,以便更好地理解创建 Widget 的源位置。源插装允许 Flutter Inspector 以类似于 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 视为相等。有关更多详细信息,请参阅关于 调试时常见问题 的讨论。

Inspector 设置

#

The Flutter Inspector Settings dialog

启用悬停检查

#

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

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

启用 Widget 树自动刷新

#

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

使用旧版 Inspector

#

启用后,请使用 旧版 Inspector 而不是新 Inspector。

包目录

#

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

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

例如,考虑以下目录结构:

project_foo
  pkgs
    project_foo_app
    widgets_A
    widgets_B

project_foo_app 运行您的应用会在 Widget Inspector 树中仅显示来自 project_foo/pkgs/project_foo_app 的 Widget。

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

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

您对包目录的更改将在下次为应用打开 Widget Inspector 时保留。

其他资源

#

要了解 Inspector 的一般功能,请参阅 DartConf 2018 演讲,其中演示了 Flutter Inspector 的 IntelliJ 版本。

要了解如何使用 DevTools 可视化调试布局问题,请查看有关 Flutter Inspector 教程 的指南。