跨端界面性能优化先修最贵的一帧

时间有限时,先在 Profile 模式找掉帧发生在哪里。build 慢就收紧状态订阅,raster 慢就检查阴影、图片和绘制范围;没有测量,不要先给全页面加 RepaintBoundary

ValueListenableBuilder<int>(
  valueListenable: selectedIndex,
  builder: (_, index, __) => TabBar(controller: controller, tabs: buildTabs(index)),
)

局部监听比页面级 setState 更容易控制影响面。静态 widget 用 const,长列表使用 builder,图片按显示尺寸解码。RepaintBoundary 只给独立且频繁重绘的局部区域,加入后要重新看 raster 时间,因为额外图层也有成本。

CI 可以运行分析和关键场景的集成测试,但阈值要来自基准设备和真实页面,不要写一个脱离环境的“必须多少毫秒”规则。每次优化都记录影响路径,下一位维护者才能知道为什么这里被拆开。

把一次卡顿拆成渲染阶段

“列表滑动不顺”只是感受,不是定位结果。Flutter 的时间线能区分 UI 线程和 raster 线程:前者高,往往是 build、布局或同步计算太多;后者高,可能是图片解码、裁剪或大面积阴影。两边都高时,也不要一次改十处。先录下能稳定复现的操作,固定数据量,再一次替换一个可疑点,否则前后的结果没有可比性。

设计稿里常见的模糊背景、圆角裁剪和叠层阴影在静态图上代价不明显,滚动起来却会反复绘制。需要保留视觉层级时,可以把背景做成预处理图片,或把昂贵区域移出滚动列表。目标不是把界面削成没有质感的白底,而是知道哪一层值得花预算。

不让优化破坏状态一致性

性能改动最容易误伤的是状态。把 widget 拆小后,要确认选中态、滚动位置和输入内容没有因为 key 变化而重置;缓存列表项后,检查数据更新是否还能刷新。只看帧率曲线很容易漏掉这些问题。

对跨端页面还应分别看 Android 和 iOS。字体度量、图片解码路径和系统动画设置并不完全一致。记录优化前后的录屏、设备型号和测试步骤即可,不必编造一个放之四海皆准的指标。下一次发现回退时,团队需要的是复现条件,而不是一句“这里曾经优化过”。

让性能记录服务于设计取舍

性能报告不必堆满图表,但要能回答一个问题:为了保留这层视觉效果,付出了哪一段交互的成本。比如首屏插画延迟出现是否比按钮不可点更可接受,列表阴影是否值得占用滚动预算。把这个决定写在改动旁边,设计和开发之后都能理解边界。

优化完成后再走一次无障碍和弱网场景。图片晚到、字体替换、系统减少动态效果,都可能改变布局与焦点顺序。流畅不是单一的帧率数字,它还包括用户操作时页面没有突然跳动或丢失上下文。

让基准长期可比较

固定测试数据和设备条件后,才有资格讨论回归。遇到系统版本变化可以更新基准,但要注明原因。持续积累的不是漂亮曲线,而是一套能帮助团队判断取舍的现场记录。

对性能敏感的组件还可以标记负责人和观测场景。改动经过这些区域时,评审者知道该重点查看滚动、输入还是图片加载,不用从头猜测。记录足够简短才有人持续维护:一次复现步骤、一个对比结果和明确的结论,通常已经够用。

这比只留下“已优化”的标签更能防止回退。

性能结论要经得起下一次复测。

Logo

一站式 AI 云服务平台

更多推荐