使用 Flutter inspector 工具
这是什么?
#Flutter widget inspector 是一个强大的工具,用于可视化和查看 widget 树。 Flutter 框架层使用 widgets 作为核心构建模块来处理从控件(例如文本、按钮和切换等)到布局(例如居中、填充、行和列等)的所有内容。 Flutter inspector 不仅可以帮助你可视化查看 Flutter widget 树,还有其他的作用:
-
了解现有布局
-
诊断布局问题
开始使用
#要调试布局问题,请在 Debug 模式 下运行应用程序,然后点击 DevTools 工具栏上的 Flutter inspector 选项打开调试面板。
可视化地调试布局问题
#下面是 Flutter inspector 工具栏中可用功能的指南。当空间有限时,将直接使用图标展示。
选择 widget 模式
启用此按钮以在设备上选择 widget 进行查看。有关更多信息,请参考 查看 widget。
刷新树
重新加载当前 widget 的信息。
慢速动画
以五分之一的速度运行动画以便对它们进行优化。
显示引导线
覆盖一层引导线以帮助调整布局问题。
显示基线
针对文字对齐展示文字的基线。对检查文字是否对齐有帮助。
高亮重绘制内容
元素重新绘制时,会依次显示不同颜色的边框。用于查找不必要的重绘。
高亮尺寸过大的图片
在运行的应用程序中高亮并反转消耗过多内存的图像。
检查一个 widget
#你可以浏览 widget 树并查看其附近的 widgets 和它们的属性值。
要在 widget 树中找到单个 UI 元素,请点击工具栏中的 Select Widget Mode 按钮。这将使设备上的应用程序进入「widget select」模式。点击应用界面上的任何 widget,将选中 widget 并将 widget 树滚动到对应的节点。再次点击 Select Widget Mode 按钮则退出「widget select」模式。
在调试布局问题时,要查看的关键字段是 size
和 constraints
。其中约束沿树结构向下传递,尺寸信息则向上返回。想要了解更多信息,可以查看 深入理解 Flutter 布局约束。
Flutter 布局浏览器
#Flutter 布局浏览器可以帮助你更好地理解 Flutter 布局。
有关此工具的操作概述,观看 Flutter Explorer 的介绍视频:
下面详细介绍的文章可能对你有帮助:
使用布局浏览器
#从 Flutter Inspector 中,选择一个 widget。布局浏览器支持 弹性布局 和固定大小的布局,并且针对它们配备了特定的工具。
弹性布局
#当你选择了一个弹性布局 widget(例如,Row
、Column
、Flex
)或它的子 widget 时,弹性布局工具将显示在布局浏览器中。
布局浏览器会直观的显示 Flex
widgets 及其子元素的布局方式。浏览器中还会显示主轴和交叉轴,以及每个轴当前的对齐方式(例如,start、end 和 spaceBetween)。它还显示了诸如弹性系数、弹性适配和布局约束等详细信息。
此外,浏览器中还会显示布局约束冲突和渲染溢出错误。正如你在设备上看到的那样,违背布局约束的地方会被标记成红色,溢出错误以标准的「黄色条带」显示。这些可视化的错误是为了让我们更好地理解溢出错误发生的原因,并了解如何修复它们。
在 Select Widget Mode 模式下,点击布局浏览器中的 widget 会同步选择到设备上。启用此模式,请点击调试面板中的 Select Widget Mode 按钮。
你可以在布局浏览器的下拉列表修改属性值,例如弹性系数、弹性适配和对齐方式。当修改 widget 的属性时,你会看到新的值同时在浏览器和运行 Flutter 应用程序的设备上生效。浏览器通过动画使更改的效果清晰可见。从布局浏览器中对 widget 属性的更改不会修改源代码,将在热重载时还原。
交互属性
#布局资源管理器支持修改 mainAxisAlignment
、crossAxisAlignment
和 FlexParentData.flex
。将来,我们可能会添加对其他属性的支持,例如 mainAxisSize
、textDirection
和 FlexParentData.fit
.
mainAxisAlignment
#支持属性:
MainAxisAlignment.start
MainAxisAlignment.end
MainAxisAlignment.center
MainAxisAlignment.spaceBetween
MainAxisAlignment.spaceAround
MainAxisAlignment.spaceEvenly
crossAxisAlignment
#支持属性:
CrossAxisAlignment.start
CrossAxisAlignment.center
CrossAxisAlignment.end
CrossAxisAlignment.stretch
FlexParentData.flex
#布局浏览器支持设置 7 种弹性因子(null、0、1、2、3、4、5),但从技术上讲,弹性 widget 子级的弹性因子可以是任何整数。
Flexible.fit
#布局浏览器支持两种不同类型的 FlexFit
:loose
和 tight
。
固定大小布局
#当你选择一个固定大小的 widget 而不是弹性 widget 时,它的布局信息将显示在布局浏览器中。你可以看到所选 widget 及其最近的上一级 RenderObject 的大小、约束和填充信息。
调试视觉效果
#The Flutter Inspector provides several options for visually debugging your app.
Flutter Inspector 提供了多种以可视化方式调试应用的方式。以下是在 Flutter DevTools 中的 inspector 可用的选项:
慢速动画
#启用时,动画将以约五分之一的原有速度运行,方便对视觉效果进行检查。当你想要仔细地观察并调试看起来不正常的动画时,这个选项会非常有用。
你也可以使用代码设置:
import 'package:flutter/scheduler.dart';
void setSlowAnimations() {
timeDilation = 5.0;
}
这会让动画时长增加 5 倍(速度减慢 5 倍)。
更多内容
#以下的链接提供了更多细节内容。
以下的录屏展示了动画减速前后的对比。
显示引导线
#该功能会在你的应用顶层绘制引导线,展示绘制区域、对齐、间距、滚动视图、裁剪和空位填充。
这个工具能帮助你更加了解你的布局。例如查找不需要的填充或者理解 widget 的对齐方式。
你也可以通过代码启用:
import 'package:flutter/rendering.dart';
void showLayoutGuidelines() {
debugPaintSizeEnabled = true;
}
Render boxes
#RenderBox
#绘制在屏幕上的 widgets 会创建一个 RenderBox,它是 Flutter 布局的基础构建。这些 RenderBox 会加上一个浅蓝色的边框:
对齐方式
#对齐方式将以黄色箭头展示。这些箭头会显示出垂直和竖屏方向上 widget 相对其父布局的偏移。例如,这个按钮图标有四个箭头表示它被居中展示:
间距
#间距会以半透明的蓝色背景显示:
滚动视图
#包含滚动内容的 widget(例如 ListView)会展示绿色的箭头:
裁剪
#使用了诸如 ClipRect Widget 进行裁剪的内容,会以粉红色的虚线加一个剪刀图标展示:
空位填充
#空位填充的 widgets 会以灰色背景展示,例如没有 child 的 SizedBox
:
显示基线
#该选项会显示所有的基线。基线是水平的用来定位文字的线。
在检查文字是否垂直对齐时,基线会非常有用。例如,下图中文字的基线稍微有一些错位:
Baseline widget 可以用来调整基线。
在设置了基线的 RenderBox 上,都会显示一条线。字母的基线以绿色展示,而符号的基线以黄色展示。
你也可以通过代码启用:
import 'package:flutter/rendering.dart';
void showBaselines() {
debugPaintBaselinesEnabled = true;
}
高亮重绘制内容
#该选项会为所有的 RenderBox 绘制一层边框,在它们重新绘制时改变颜色。
以彩虹色谱循环的颜色,有利于你找到应用中频繁重绘导致性能消耗过大的部分。
例如,一个小动画可能会导致整个页面一直在重绘。将动画使用 RepaintBoundary widget 嵌套,可以保证动画只会导致其本身重绘。
下面是一个进度指示器导致其容器重绘的例子:
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(),
),
);
}
}
将进度指示器使用 RepaintBoundary
包裹,可以将重绘范围缩小至它本身占有的区域。
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(),
),
),
);
}
}
RepaintBoundary
widget 也有一些额外的消耗。它们对性能有一定的帮助,但也会在创建额外的绘制画布时增加一定的内存消耗。
你也可以通过代码启用:
import 'package:flutter/rendering.dart';
void highlightRepaints() {
debugRepaintRainbowEnabled = true;
}
高亮尺寸过大的图片
#该选项会将尺寸过大的图片高亮表示,并且进行垂直翻转及色调反转:
被高亮的图片使用了过多的内存。例如一张 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
构造里的
cacheHeight
和 cacheWidth
参数:
class ResizedImage extends StatelessWidget {
const ResizedImage({super.key});
@override
Widget build(BuildContext context) {
return Image.asset(
'dash.png',
cacheHeight: 213,
cacheWidth: 392,
);
}
}
这样的方法可以让引擎以指定的大小解析图片,减少内存的消耗(解析开销和空间占用相较图片调整图片本身仍然较大)。无论如何设置参数,图片依然会以布局限制或大小进行渲染。
该属性同样可以使用代码设置:
void showOversizedImages() {
debugInvertOversizedImages = true;
}
更多内容
#以下的链接提供了更多细节内容:
树的详细信息
#选择 Widget Details Tree 标签来显示选中 widget 的详细信息树。从这里,你可以收集关于 widget 属性、渲染对象和子节点的有用信息。
追踪 widget 创建
#Flutter inspector 的部分功能是基于检测应用程序的源码,以便更好地理解创建 widget 的源位置。 Flutter inspector 可以以类似于在源代码中定义 UI 的方式呈现 widget 树。如果没有它,widget 树中的组成某个节点的树结构会更深,并且更难理解运行时 widget 的层次结构如何与应用程序的 UI 相对应。
你可以通过在 flutter run
后面添加参数 -no track widget creation
来禁用此功能。
下面是 widget 树在启用和不启用追踪 widget 创建下的示例。
启用追踪 widget 创建(默认):
关闭追踪 widget 创建(不推荐):
此功能可避免在调试构建中将其他相同的 const
的 Widgets 视为相同。有关更多详细信息,请参阅关于 调试时常见问题 的讨论。
设置 Inspector
#启用 hover 检测 (Enable hover inspection)
#将鼠标悬停在任意 widget 上,会显示该 widget 的属性和值。
你可以切换 Enable hover inspection 启用或禁用 hover 检测功能。
Package 目录 (Package Directories)
#默认情况下,DevTools 会根据项目根目录中的 widget 和 Flutter 中的 widget,限制 widget 树中的显示。这种过滤仅适用于 Inspector Widget Tree(Inspector 左侧)中的 widget -- 不适用于 Widget Details Tree (Inspector 右侧,与 Layout Explorer 处于同一选项卡视图中)。在 Widget Details Tree 中,你可以看见树中所有 package 的 widget。
要显示其他 widget,必须在 Package Directories 中添加它们的父目录。
例如,以下目录结构:
project_foo
pkgs
project_foo_app
widgets_A
widgets_B
从 project_foo_app
运行应用时,只会在 widget inspector 树中显示 project_foo/pkgs/project_foo_app
的 widget。
如果需要在 widget 树中显示 widgets_A
的 widget,请在 Package Directories 中添加 project_foo/pkgs/widgets_A
。
如果需要在 widget 树中显示项目根目录下的 所有 widget,请在 Package Directories 中添加 project_foo
。
你对 Package Directories 的更改是一直存在的,下次打开应用程序的 widget inspector 时依旧生效,
其他资源
#有关 Flutter inspector 常用功能的演示,请参考 DartConf 2018 talk 中基于 IntelliJ 上的演示。
想要学习如何使用 DevTools 以可视化的方式调试布局问题,可以阅读 Flutter 布局检查器教程。
除非另有说明,本文档之所提及适用于 Flutter 的最新稳定版本,本页面最后更新时间: 2024-11-02。 查看文档源码 或者 为本页面内容提出建议。