Flutter性能监控插件fps_monitor的使用
Flutter性能监控插件fps_monitor的使用
导语
对于任何一款应用而言,页面的流畅度一定是影响用户体验最重要的几个指标之一。作为开发者,优化页面流畅度也是自己技术实力的体现。但在决定进行优化之前,还有两个更重要的问题摆在我们面前:1、如何发现卡顿的页面?、2、如何衡量我的优化效果?
为了解决这两个问题,本期给大家带来一个很有用的小工具:fps_monitor
一、What’s this 这是个什么工具?
这是一个能在 profile/debug
模式下,直观帮助我们评估页面流畅度的工具。直白来说就是:这是一个可以在(刷新率60)设备上直接查看最近(默认 100)帧的表现情况的小工具,直接上图:
当我们点击右下角的 ⏯ 后,按钮变为⏸ 状态,工具开始为我们收集每一帧的总耗时(包含 CPU 和 GPU 耗时)。此时点击 ⏸ 按钮会为我们展示收集到的耗时信息。
柱状图顶部为我们展示收集到的数据里:最大耗时、平均耗时、以及总耗时(单位:毫秒)。在下方,我将页面流畅度划分为四个级别:流畅(蓝色)、良好(黄色)、轻微卡顿(粉色)、卡顿(红色),将 FPS 折算成一帧所消耗的时间,不同级别采用不一样的颜色,统计不同级别出现的次数。
上面的例子中,我们可以看到,工具一共收集了 99 帧,最大耗时的一帧花了119ms,平均耗时:32.9 ms,总耗时:3259.5 ms。其中认为有 40 帧流畅,25 帧良好,38 帧轻微卡顿,6 帧卡顿。
二、Why you need this 为什么你需要这个工具?
1、为什么我没选择 PerformanceOverLay 和 DoKit?
看到上面的功能可能有人有疑惑,你这功能咋和 PerformanceOverLay 这么类似?
首先,我在使用 PerformanceOverLay 的时候遇到了一点问题:
如图,PerformanceOverLay 上分别为我们展示了构建(UI)耗时和渲染(GPU)耗时。
我遇到的第一个问题是,因为我们在判断流畅度的时候,往往是看一帧的总耗时。这样拆分之后,一帧的耗时变成了上下的和,对我而言很不直观。
其次,这里面提供最大耗时
或者平均耗时
并不能很好地帮助我们量化页面的流畅程度。因为这个统计过程,会直接将一帧的耗时进行平均,这就带来一个问题。我们知道对于60刷新率的设备,两帧的间隔时间最小应该是 16.7ms,而 PerformanceOverLay 的收集过程没有对数据过滤,会出现一帧耗时小于 16.7ms,这就导致平均数据可能偏低。(下图平均一帧耗时为:10.6ms 60HZ设备)
其实这样来看,DoKit是一个不错的选择
但DoKit同样没有对最小帧耗时做过滤,也会出现平均耗时偏低的情况。同时,没有更多的数据辅助评估页面的流畅程度。
上面我遇到的情况,不一定是问题,只是我在使用过程中觉得不太直观,不太方便。
因此开发了这个工具,该工具具有以下特点
同时支持设置最大采集帧数
2、我是如何理解页面流畅度
对于大部分人而言,当每秒的画面达到60,也就是俗称60FPS的时候,整个过程就是流畅的。
一秒 60 帧,也就意味着平均两帧之间的间隔为 16.7ms。那么耗时大于 16.7ms 就会觉得卡顿么?
答案当然是 NO。腾讯在 Matrix 中也提到
我们平时看到的大部分电影或视频 FPS 其实不高,一般只有 25FPS ~ 30FPS,而实际上我们也没有觉得卡顿。 在人眼结构上看,当一组动作在 1 秒内有 12 次变化(即 12FPS),我们会认为这组动作是连贯的
其实流畅度本身就是一个很主观的东西,就好比有人觉得打王者荣耀不开高帧率好像也还算流畅,有人觉得不开高帧率那不就是个GIF图么。
有没有客观一点的指标,我在网上查询了很久之后找到了一篇08年发表在ICIP上的论文,他们使用了6种内容进行测试,实验结果如下图所示
通过该图我们可以看出,当帧率大于15帧的时候,人眼的主观感受差别不大,基本上都处于较高的水平。而帧率小于15帧以后,人眼的主观感受会急剧下降。换句话说,人眼会立刻感受到画面的不连贯性。
因此,在工具中我将低于16.7ms的数据统一成16.7ms,所以这个检测工具只在刷新率为60的设备有意义。并且将流畅度划分为了以下等级:
- 流畅:FPS大于55,即一帧耗时低于 18ms
- 良好:FPS在30-55之间,即一帧耗时在 18ms-33ms 之间
- 轻微卡顿:FPS在15-30之间,即一帧耗时在 33ms-67ms 之间
- 卡顿:FPS低于15,即一帧耗时大于 66.7ms
并统计出现的次数,你可以根据这几项数据,对比优化前后的数据,得出性能的提升情况;当然也可以制定一个理想的流畅度。例如:流畅的帧数占统计帧数的90%,或者卡顿的帧数不超过5次。
三、How to use it 如何使用?
1、项目依赖
dependencies:
fps_monitor: ^1.12.13-1
2、接入工程
有两处接入点:
- 指定overLayState ,因为需要弹出一个Fps的统计页面,所以当前指定overLayState。
(PS:大家一般使用
Navigator.of(context)
去跳转一个页面,通过GlobalKey
可以实现无context的跳转)
///声明NavigatorState的GlobalKey
GlobalKey<NavigatorState> globalKey = GlobalKey();
///获取overLayState
SchedulerBinding.instance.addPostFrameCallback((t) =>
overlayState = globalKey.currentState.overlay
);
///指定MaterialApp的navigatorKey
navigatorKey: globalKey,
- 在build属性中包裹组件
builder: (ctx, child) =>
CustomWidgetInspector(
child: child,
),
3、如何使用
在完成了上述步骤之后,你只需要启动app,该工具只会在profile/debug模式下集成,在你的右下角会出现一个 ⏯ 按钮,点击开始记录,再次点击显示数据。
如果想要结束采集,点击面板中的停止监听即可。
如果你想采集更多的帧,可以通过kFpsInfoMaxSize
设置
4、Warning
空安全之前 请使用 1.12.13-2 分支
空安全后 使用 2.0.0 分支
四、how do it 来点原理?
可能你会对这个工具的检测原理感兴趣,那咱们再来唠两句原理。
绘制数据的获取
WidgetsBinding.instance.addTimingsCallback(monitor);
Flutter 会在每帧完成绘制后,会将耗时进行回调。耗时体现在三个变量上:1、构建时间;2、绘制时间;3、总时间。当你点击 ⏯ 按钮的时候,工具便开始采集耗时信息。
其实对于 Flutter 相关的渲染调度,推荐大家看看 SchedulerBinding
,里面写得再详细不过。
显示Fps界面
显示 Fps 的页面比较简单,直接通过 OverlayState
插入即可。如果你不太熟悉 Overlay
可以把它理解成浮窗。其中的表格绘制通过使用 DoKit 的自定义画笔实现,当然也可替换成各种开源的图表库。
最后 感谢各位吴彦祖和彭于晏的点赞,Start,和Follow
如果你觉得这个工具还不错,点个赞支持一下吧~
最后附上我的公众号:进击的Flutter或者runflutter 里面整理收集了最详细的 Flutter 进阶与优化指南。关注我,获取我的最新文章~
如果使用过程有问题可以直接通过公众号私信我~
完整示例 Demo
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:fps_monitor/widget/custom_widget_inspector.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
GlobalKey<NavigatorState> globalKey = GlobalKey();
WidgetsBinding.instance.addPostFrameCallback((t) {
overlayState = globalKey.currentState.overlay;
});
return MaterialApp(
navigatorKey: globalKey,
title: 'Flutter Demo',
builder: (ctx, child) => CustomWidgetInspector(
child: child,
),
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
[@override](/user/override)
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
)
],
),
),
);
}
}
更多关于Flutter性能监控插件fps_monitor的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter性能监控插件fps_monitor的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中集成和使用fps_monitor
插件来监控应用性能的示例代码。fps_monitor
插件可以帮助你实时监控应用的帧率(FPS),这对于性能调优和用户体验优化非常有用。
步骤 1: 添加依赖
首先,你需要在pubspec.yaml
文件中添加fps_monitor
依赖:
dependencies:
flutter:
sdk: flutter
fps_monitor: ^0.3.0 # 请检查最新版本号
然后运行flutter pub get
来安装依赖。
步骤 2: 导入和使用 FPS Monitor
接下来,在你的Flutter应用中导入并使用fps_monitor
。以下是一个简单的示例,展示如何在应用中显示FPS。
主文件 (main.dart)
import 'package:flutter/material.dart';
import 'package:fps_monitor/fps_monitor.dart';
void main() {
// 初始化 FPS Monitor
FPSMonitor.init();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter FPS Monitor Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String fps = 'FPS: 0';
@override
void initState() {
super.initState();
// 开始监听 FPS
FPSMonitor.addListener(() {
setState(() {
fps = 'FPS: ${FPSMonitor.instance.fps.toInt()}';
});
});
}
@override
void dispose() {
// 停止监听 FPS
FPSMonitor.removeListener(() {});
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter FPS Monitor Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(fps, style: TextStyle(fontSize: 24)),
],
),
),
);
}
}
解释
- 初始化 FPS Monitor: 在
main
函数中调用FPSMonitor.init()
来初始化FPS监控器。 - 添加监听器: 在
initState
方法中,通过FPSMonitor.addListener()
添加一个监听器,该监听器会在每次FPS更新时调用。在监听器内部,使用setState
更新UI,显示当前的FPS值。 - 移除监听器: 在
dispose
方法中,通过FPSMonitor.removeListener()
移除监听器,以避免内存泄漏。 - 显示FPS: 在UI中,使用
Text
组件显示当前的FPS值。
运行应用
完成上述步骤后,运行你的Flutter应用。你应该会在应用的界面上看到实时的FPS值。
注意
- 确保你使用的是最新版本的
fps_monitor
插件,因为插件的API可能会随着版本更新而发生变化。 - FPS监控通常用于开发和调试阶段,不建议在生产环境中使用,因为它可能会增加应用的开销。
这样,你就可以使用fps_monitor
插件来监控你的Flutter应用的性能了。希望这对你有所帮助!