美文网首页
Flutter流畅度优化之过度绘制

Flutter流畅度优化之过度绘制

作者: 厘米姑娘 | 来源:发表于2023-04-02 19:46 被阅读0次

    一些容易被忽视导致过度绘制的组件。

    发现问题

    Flutter官方提供的性能检测工具DevTools可用来检测如不合理布局(Inspector)、单帧CPU耗时(Performace)、方法耗时(CPU Profiler)、内存情况(Memory)等,这里主要分析帧率。

    如图所示,最上方的柱状图显示了时间轴上每一帧耗时情况,包括两部分,淡蓝色为UI线程、深蓝色为GPU线程,若该帧耗时超过 16ms会变为红色,也是分析的重点。选中一帧,在下方就会具体展示两个线程的事件流情况,帮助排查卡顿原因。

    原因分析

    选取一段可看到U线程的paint耗时明显过长,且前后帧也是类似。

    我们知道UI线程慢核心就是渲染(build、layout、paint)慢,常见的build引发的性能问题就是不该重建的组件被重建了,因此使用setState方法要遵从最小范围刷新原则,避免过度刷新;那paint耗时长又是什么原因导致的呢?

    这里需要切换到Debug模式(实际性能分析用Profile模式),然后借助Inspector中的Highlight repaints功能查找不必要的重绘组件,启动后会在组件四周加上边框,当元素发生重绘边框颜色就会改变。

    值得一提的是,这里其他的小工具也很好用,如Slow animations将动画速度放慢 5 倍便于调整动画、Show guidelines可以显示具体布局情况便于调整布局、Show baselines显示文本基线便于对齐文本、Highlight oversized images通过翻转颜色和垂直翻转提示哪些是占用过多内存的图像,详细可以翻阅官方介绍文档

    解决方案

    打开Highlight repaints后发现,确实存在页面不停地重绘的现象,尤其在视频做启播loading时,边框在一直变色(见左图)。其实官方例子里提到了这种进度条组件,解决办法就是在外面套一层RepaintBoundary组件,给子项创建一个单独的显示图层,将重绘范围限制在子项内。

    此时,当子树的重绘时间与树其他部分不同时可以提高性能,因为每当共享同一层的任何 RenderObjec被标记为脏且需要绘制时,关联的Widget即使没有更改或重建,也会触发RenderObject.paint。
    RepaintBoundary创建了一个始终具有Layer的RenderObject,从而将祖先渲染对象与后代渲染对象分离。

    加上RepaintBoundary后进度条的重绘范围确实变化为仅限自己,但此时仍有不停重绘的问题(见右图),看来还有其他组件在请求重新绘制。

    通过观察发现右上角带有Gif挂件的卡片就会变色,同样的,在顶部导航栏也有Gif Tab,类似的,像点赞Lottie动画都会导致渲染树被重新绘制,都处理后的效果如图,页面不相关组件不再被重绘了:

    总结

    在添加动画、Gif、Lottie时,需要注意是否会导致不必要的组件被重绘,尤其在关键路径,可以通过RepaintBoundary将多变和不变的图层分离开,提高paint性能。

    相关文章

      网友评论

          本文标题:Flutter流畅度优化之过度绘制

          本文链接:https://www.haomeiwen.com/subject/wgirddtx.html