Flutter性能优化

性能分析工具

(1)performance overlay

开启performance overlay后,Flutter APP上将显示一个展示一个浮层,浮层中会实时展示当前的UI线程及Raster线程的运行情况。如果都是蓝色竖条,说明界面运行流畅,否则则是出现掉帧。

performance overlay可以直接通过代码开启:

Dart 复制代码
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(

      //开启性能监控浮层
      showPerformanceOverlay: true,

      title: 'MyApp',
      home: MyHomePage(title: 'My Awesome App'),
    );
  }
}

也可以在Debug过程中,在VSCode右侧的Performance 中点击 Toggle Performance Overlay 开启。

(2)DevTools

使用DevTools除了可以像performance overlay那样查看App的运行情况,还会录制具体的每一帧绘制及渲染的详细过程,并且允许用户选择任何一帧,查看其运行详情。

比较重要的主要是Enhance Tracing中的几个选项

选取Track Widgets Build,可以查看某一帧build执行的详情

如果发现build执行的层级比较深,则说明是一个比较"大"的Widget执行了重建。那我们就需要研究下这种重建是否是必要的。比如,如果只是其中某个小组件的数据发生了变化,就可以优化只对小组件进行重建。又比如,数据未发生变化,但重建的频率非常高,则需要看一下导致重建的原因,看是否可以取消执行这种不必要的逻辑。

选取TrackPaints, 则可以追踪当前帧绘制的主要逻辑

如果发现paint的层级比较深,则很可能是有比较大的Widget执行了绘制相关逻辑,那么就可以看下这种大Widget执行重绘是什么引起的,以及是否有必要。如果是小组件的重绘导致的,可以尝试用RepaintBoundary包裹小组件,使得重绘仅限于小组件自身。

性能优化总结

(1)图片等资源访问使用内存缓存及本地文件缓存。Flutter对GlobayKey组件有缓存,对构建复杂,并且复用率比较高的组件,合理使用GlobayKey可以提升性能。但需注意, 使用GlobayKey查找组件state是全局查找,有较大性能开销,查找不能滥用。
(2)提高build效率:避免大的widget反复重新build:将需要重新build的子widget改为自定义的statefulWidget, 在该widget内调用setState进行重新构建,而不是对整个大的widget都重新构建; 或者用consumer实现局部刷新。

(3)提高Paint效率, 需要重绘的widget用RepaintBoundary包住,变为其child,进而创建一个单独的layer,对其重绘制不影响其它组件。适合用RepaintBoundary包住的组件主要是两类, 一是需要频繁重绘的组件,使用RepaintBoundary后就可以不影响其它组件;另一种是绘制比较复杂的小组件,而除了该组件外其他组件不会变化,也适合用RepaintBoundary将其变为一个独立的图层以提升效率。

(4)尽量多使用const实例或widget 的const构造方法, 能用statelessWidget实现的就不要用StatefulWidget实现。尽量利用缓存,减少组件的重新渲染。

(5)build方法中耗时使用异步, 更耗时的计算操作可以使用compute启用多线程。但要注意, Flutter中开启线程实际会创建一个新的isolate, 线程启动不仅耗时,还会增加内存占用,开启线程应避免滥用

(6)尽量减少Widget子组件的层级。比如Row或者Column组件中减少Padding的使用, 用sizebox来实现组件位置的偏移

(7)ListView应采用build方法进行按需构建,避免一次性构建过多的item,或者使用性能更好的CustomScrollView;可折叠的listview在折叠状态时,设itemCount为0; 尽量避免设置widget为半透明,避免下方内容不必要的绘制,可以用截图来实现半透效果。

(8)降级CustomScrollView,ListView上下各250高度的执行渲染,这就是预渲染区。预渲染区在性能较差机器可以通过参数调整到更小的高度。此外,Flutter为提升Listview滚动性能, 默认会用widget包裹Listview中的子组件,并让被包裹的组件仅绘制一次,但这会带来更大的内存占用。如果内存资源比较稀缺,可以通过ListView的addAutomaticKeepAlives和addRepaintBoundaries属性禁用该特性。

Dart 复制代码
ListView.builder(
  ...
  addAutomaticKeepAlives: false (true by default)
  addRepaintBoundaries: false (true by default)
);

如果ListView和Gridview中Item的高度时固定的,还可以使用itemExtent实现滚动条大高度滚动的效率。

(9)减少图像裁剪性能开销: 尽量少用ClipRRect组建,改为使用BoxDecoration组件的image属性。

相关推荐
jump_jump16 小时前
流式 HTML:从 htmx 片段装配到浏览器原生增量渲染
javascript·性能优化·前端工程化
悟空瞎说19 小时前
Flutter 架构详解:新手必懂底层原理
flutter
SoaringHeart21 小时前
Flutter最佳实践:IM聊天文字链接自动识别跳转
前端·flutter
恋猫de小郭1 天前
KMP / CMP 鸿蒙版本 Beta 发布,他有什么特别之处?
android·前端·flutter
小小工匠2 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
风华圆舞2 天前
Flutter + 鸿蒙 Intents Kit:页面直达能力的完整接入方案
flutter·ui·华为·harmonyos
韩曙亮2 天前
【Flutter】Flutter 组件 ④ ( 组件渲染 的 三棵树理论 | Widget 树 → Element 树 → RenderObject 树 )
flutter·element·widget·renderobject
大鱼>2 天前
地平线BPU部署实战:YOLOv8在J5/X3上的算法适配与性能优化
算法·yolo·性能优化
醉颜凉2 天前
Elasticsearch高性能优化:Bulk API大规模数据导入性能调优全攻略
elasticsearch·性能优化·jenkins
隔窗听雨眠2 天前
C语言函数递归从入门到精通(下):性能优化与工程实践
c语言·算法·性能优化