Flutter应用如何调试–DevTools介绍(上)
Flutter应用如何调试–DevTools介绍(中)
Flutter应用如何调试–DevTools介绍(下)
接着上篇,本篇进行一下的介绍
- Performance
- Debugger
- Network
- Logging
Performance
性能视图可以记录并分析 Flutter 和 Dart 应用的性能,以帮助我们找到应用程序的性能瓶颈。初始进来页面是空的,单击 Record
开始进行记录 CPU 信息,完成后点击 Stop
停止记录,CPU分析器会把收集的信息推送到VM并分别在不同的信息窗口进行展示调用树 (Call Tree
, Bottom Up
, and Flame Chart
),这里的采集也分低、中、高三个类型的粒度,在DevTools介绍(二中)
已经有介绍。
Flame Chart
火焰图表
火焰图选项卡主要用于显示一段持续时间内 CPU 的样本信息。图表展示的是自上而下的调用堆栈信息,即上面的堆栈帧调用下面的堆栈帧。每一个堆栈帧的宽度代表 CPU 执行的时长。栈帧消耗 CPU 的时间越长,就越洽有可能是我们进行性能改进的好地方。
Call Tree
调用树(也叫跟踪树)
调用树视图是一种自上而下展示 CPU 中的调用堆栈信息方法。在下图中的表格中可以看出,展开其中的一个方法可以查看它所有的调用者。
Bottom Up
ottom Up视图也是用于显示方法调用堆栈,但顾名思义,它是一个自下而上的表示方式。这意味着表格中的每个最上方的方法实际上是给定 CPU 样本的调用堆栈中的最后一个方法 (换句话说,这是样本的叶节点)。
在DevTools
中的Performance
中我并没有看出可以指导代码进行优化的地方,并且devTools的Performance工具运行在Profilr
模式下,但是在dubug
模式下的Android Stdio右侧的Flutter Performance
中,找到了一些可以帮助调试信息,即Track widget rebuilds
,这在Profilr
模式下反而不能用,因为DevTools
还是beta版本本,可能一些功能还不完善。
在这里我们可以看到哪些widget进行了多少次构建,右边第二列显示了所在框架的重载次数。如果重载次数过多,会显示一个黄色旋转圆圈。最右一列显示了进入当前页面后 widget 的重载次数。对于未重载的小部件,将显示一个灰色圆圈,否则将显示一个灰色旋转圆圈。
该工具可以帮助你调试至少四个常见的性能问题:
整个屏幕(或大部分屏幕)由一个 StatefulWidget 构成,导致不必要的 UI 构建。可将 UI 拆分成多个具有较轻量 build() 方法的 widget。
未在屏幕上显示的 widget 发生了重载。例如,一个延伸到屏幕外的 ListView,或者未给延伸到屏幕外的列表设置 RepaintBoundary,会导致重绘整个列表。
AnimatedBuilder 的 build() 方法绘制了一个不需要动画的子树,导致不必要的静态对象重载。
一个 Opacity widget 在 widget tree 中使用了一个不必要的高度,或者通过直接操作 Opacity widget 的透明属性创建 Opacity 动画,导致 widget 和它的子树重载。
关于性能优化部分,之后会再写一篇文章专门谈Flutter的性能优化。
这里简单介绍一下,如何找出影响Flutter性能的最大问题,即saveLayer()
的过多调用。调用 saveLayer() 会开辟一片离屏缓冲区。将内容绘制到离屏缓冲区可能会触发渲染目标切换,这些切换在较早期的 GPU 中特别慢。
我们可以在MaterialApp
中属性设置
showPerformanceOverlay: true,
// 检查场景是否使用了 saveLayer,使用了saveLayer的图像轮廓会随着页面刷新而闪烁
checkerboardOffscreenLayers: true,
// 做了缓存的静态图像图片在刷新页面使不会改变棋盘格的颜色;如果棋盘格颜色变了,说明被重新缓存,这是我们要避免的
checkerboardRasterCacheImages: true,
Debugger
debug看见名字就能知道是运行在debug模式下,这里可以进行断点调试,对于命令行开发来说是一个便捷的调试工具
除了使用命令行工具开发以外,还是建议使用IDE进行调试,功能更强大一些,这里就不做过多介绍。
值得补充一点的是,在Android studio中,运行和debug调试是两种构建方式,如果当前是在Run
运行状态,不想切换到debug模式,这时候又想进行调试的话,可以添加如下代码进行断点,在Devtools
中查看。
import 'dart:developer' as developer;
developer.debugger(when: index == 5);
Network
网络视图使您可以从Dart或Flutter应用程序检查HTTP网络流量。
可以检查有关请求的常规信息,以及响应和请求标头,其余作用有限。
Logging
日志视图展示 Dart 运行时和应用框架(比如 Flutter)的事件,以及应用级日志。
- 默认情况下,日志视图会展示:
- Dart 运行时的垃圾回收事件
- Flutter 框架事件,比如创建帧的事件
- Flutter framework events, like frame creation events
- 应用的 stdout 和 stderr 输出
- 应用的自定义日志事件
logging信息经过调研,我个人还没太明白其作用,因为自动输出的log信息太多,里面又全是看不太明白的信息
{
"type": "Event",
"kind": "Extension",
"extensionKind": "Flutter.RebuiltWidgets",
"isolate": {
"type": "@Isolate",
"id": "isolates/3650949643688903",
"name": "main",
"number": "3650949643688903"
},
"timestamp": 1596348786926,
"extensionData": {
"startTime": 1248147575,
"events": []
}
}
当然我们可以自定义log,进行输出,帮助我们排查信息,在官方文档中以编程的方式调试应用部分有一点介绍,内容有限。
我们可以直接使用stdout 和 stderr
输出信息
stdout.writeln('test1111');
也可以通过developer方式输出
import 'dart:convert';
import 'dart:developer' as developer;
void main() {
var myCustomObject = ...;
developer.log(
'log me',
name: 'my.app.category',
error: jsonEncode(myCustomObject),
);
}
对应的logging里面则会记录
其他
介绍到这里DevTools的使用基本结束,本文主要基于Android Studio工具进行讲解,当然也可以通过编程的方式进行,添加输出代码的方式调试 Flutter 应用
此外这里有一篇文章介绍devtools是如何工作的,以及Google Flutter团队的视频Flutter Inspector (DartConf 2018
来自谷歌开发者的介绍我们用 Flutter 写了一套全新的 Flutter 开发者工具