一、这是什么?
Flutter widget inspector是一个强大的工具,用于可视化和查看widget树。Flutteer框架层使用widgets作为核心构建模块来处理空间(例如文本、按钮和切换等)到布局(例如居中、填充、行和列等)的所有内容。Flutter inspector不仅可以帮助你可视化查看Flutter widget树,还有其他的作用:
- 了解现有布局
- 诊断布局问题
二、开始使用
要调试布局问题,请在Debug模式下运行应用程序,然后点击DevTools工具栏上的Flutter inspector选项打开调试面板。
2.1、可视化地调试布局问题
下面是Flutter inspector工具栏中可用功能指南。当空间有限时,将直接使用图标展示。
选择 widget 模式:启用此按钮以在设备上选择wiidget进行查看。
刷新树:重新加载当前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之Layout Explorer初体验
4.1、使用布局浏览器
从Flutter Inspector中,选择一个widget。布局浏览器支持弹性布局和固定大小的布局,并且针对它们配备了特定的工具。
4.1.1、弹性布局
当你选择了一个弹性布局widget(例如,Row、Column、Flex)或它的子widget时,弹性布局工具将显示在布局浏览器中。
布局浏览器会只管显示Flex widgets以及其子元素的布局方式。浏览器中还显示主轴和交叉轴,以及每个轴当前的对齐方式(例如,start、end和spaceBetween)。它还显示了诸如弹性系数、弹性是适配和布局约束等详细信息。
此外,浏览器中还会显示布局约束冲突和渲染溢出错误。正如你的设备上看到的那样,违背布局约束的地方会被标记红色,溢出错误已标准的「黄色条带」显示。这些可视化的错误是为了让我们更好地理解溢出错误发生的原因,并了解如何修复它们。
在Select Widget Mode模式下,点击布局浏览器中的widget会同步选择到设备上。启用此模式,请点击调试模版中的Select Widget Mode按钮。
你可以在布局浏览器的下拉列表修改属性值,例如弹性系数、弹性适配和对其方式。当修改widget的属性时,您会看到新的值的同时在浏览器和运行Flutteer应用程序的设备上生效。浏览器通过动画使更改的效果清晰可见。从布局浏览器中对widget属性的更改不会修改源代码,将在热重载时还原。
4.1.2交互属性
布局资源管理器支持修改mainAxisAlignment、crossAxisAlignment和RlexparentData.flex.将来,我们可能会添加对其他属性的支持,例如mainAxisSize、textDirection和FlexPareentData.fit。
- mainAxisAlignment
支持属性:
MainAxisAlignment.startMainAxisAlignment.endMainAxisAlignment.centerMainAxisAlignment.spaceBetweenMainAxisAlignment.spaceAroundMainAxisAlignment.spaceEvenly
- crossAxisAlignment
支持属性:
- CrossAlignment.start
- CrossAlignment.center
- CrossAlignment.end
- CrossAlignment.stretch
- FlexParentData.flex
布局浏览器支持设置7种弹性因子(null、0、1、2、3、4、5),但从技术上讲,弹性widget子级的弹性因子可以是任何整数。
- Flexible.fit
布局浏览器支持两种不同类型的FlexFit:loose和tight。
4.1.3、固定大小布局
当您选择一个固定大小的widget而不是弹性widget时,它的布局信息将显示在布局浏览器中。你可以看到所有widget及其最近的上一级RenderObject的大小、约束和填充信息。
五、调试视觉效果
Flutter Inspector提供了多种可视化方式调试应用的方式。以下是在Flutter DevTools中的inspector可用选项:
5.1、慢速动画
启用时,动画将以五分之一的原有速度运行,方便对视觉效果进行检测。当你想要仔细检查并调试看起来不正常的动画时,这个选项会非常有用。
你也可以使用代码设置:
import 'package:flutter/scheduler.dart';
void setSlowAnimations() {
timeDilation = 5.0;
}
这会让动画时长增加5倍(倍速减慢5倍)。
下面的录屏展示了动画减速前后的对比。
5.2、显示引导线
该功能会在您的应用顶层绘制引导线,展示绘制区域、对齐、间距、滚动视图、裁剪和空位填充。
这个工具能帮助你更加了解你的布局。例如查找不需要的填充或理解widget的对齐方式。
你也可以通过代码启用:
import 'package:flutter/rendering.dart';
void showLayoutGuidelines() {
debugPaintSizeEnable = true;
}
5.2.1、Render boxes
RenderBox
绘制在屏幕上的widgets会创建一个RenderBox,它是Flutter布局的基础构建。这些RenderBox会加上一个浅蓝色的边框。
5.2.2、对齐方式
对齐方式将黄色箭头展示。这些箭头会显示出垂直和竖屏方向的widget相对其付布局的偏移。例如,这各个按钮图标有四个箭头表示它被居中展示:
5.2.3、间距
间距会以半透明的蓝色背景显示:
5.2.4、滚动视图
包含滚动内容的widget(例如ListView)会展示绿色的箭头:
5.2.5、裁剪
使用了诸如ClipRect Widget进行裁剪的内容,会以粉红色的虚线加一个剪刀图标展示:
5.2.6、空位填充
空位填充的widgets会以灰色背景展示,例如没有child的SizedBox:
5.3、显示基线
该选项会显示所有的基线。基线是水平的用来定位文字的线。
在检查文字是否垂直对齐时,基线会非常有用。例如,下图中文字的基线稍微有一些错位:
Baseline widget可以用来调整基线。
在设置了基线的RenderBox上 ,都会显示一条线。字母的基线是以绿色展示,而符号的基线以黄色展示。
你可以通过代码启用:
import 'package:flutter/rendering.dart';
void shoowBaselines() {
debugPaintBasselinesEnabled = true;
}
5.4、高亮重绘制内容
该选项会为所有的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() {
debugRepaintRainbowEnable = true;
}
5.5、高亮尺寸过大的图片
该选项会将尺寸过大的图片高亮表示,并且进行垂直翻转及色调反转:
被高亮的图片使用了过多的内存。例如一张5MB大小的图片以100x100像素展示。
这样的图片会导致性能低下,在低端设备上尤为明显,而当你在诸如列表中有大量这样的图片时,性能的下降会叠加。调试控制台窗口会打印每个图片的信息:
dash.png has a display size of 213×392 but a decode size of 2130×392, which uses an additional 2542KB.
超过128KB的图片被视为过大。
5.5.1、调整图片
在可能的情况下,最好的办法是调整图片资源的大小,让它变得更小。
如果该方法不可行,你可以使用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;
}
六、树的详细信息
选择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视为相同。