Flutter列表性能优化

一.内存优化

1.识别出消耗多余内存的图片

Flutter Inspector:点击Highlight oversized images,会解码出那些大小超过展示大小的图片,并且系统会将其倒置突出显示。

此类图片会导致性能不佳,尤其是在低端设备上,并且当有许多图片(例如在列表视图中)时,这种性能影响可能会增加。

如果图片使用的大小至少比要求的大128KB,则图片被视为太大。

修复图片:
<1>.解决此问题的最佳方法是调整图片资源文件的大小,使其更小。
<2>.如果这是不可能的,可以在加载图片时使用cacheWidthcacheHeight参数,这使引擎以指定大小解码该图片,并减少内存使用(解码和存储仍然比缩小图片资源本身更昂贵)。

2.避免在快速滚动时加载图片

使用官方的ScrollAwareImageProvider组件,会在列表快速滑动时中断图片的下载和解码,从而减少不必要的内存占用。

虽然这种方法不能100%解决图片加载时 OOM 的问题,但是很大程度优化了列表中的图片内存占用,官方提供的数据上看理论上可以在原本基础上节省出 70% 的内存。

3.不要使用shrinkWraptrue

Flutter团队将从滑动控件里面弃用shrinkWrap属性,因为团队觉得现阶段的开发人员大多数时候不知道它的实际含义,只是单纯使用它解决问题,在使用过程中容易出现错误的性能损耗而不自知。

shrinkWrap:true的时候,在滑动控件内部会采用一个特殊的ShrinkWrappingViewport窗口进行实现,ShrinkWrappingViewport是调整自身大小去匹配主轴方向中Item的大小,这种收缩的行为成本会变高,因为窗口大小需要通过Item去确定。

shrinkWrap:true会将列表所有的item都构建完成,尽管他们还远没有在 ViewPort展示出来,所以shrinkWrapListView失去了懒加载的作用,导致内存性能问题。

4.addAutomaticKeepAlivesaddRepaintBoundaries

addAutomaticKeepAlives:true表示将item包裹在AutomaticKeepAlive组件中,当item滑出屏幕时不会被GC(垃圾回收),会使用KeepAliveNotification来保存其状态,从而在再次出现在屏幕的时候能够快速构建。这其实是一个拿空间换时间的方法,会造成一定程度的内存开销。

addRepaintBoundaries:true表示将item包裹在RepaintBoundary组件中,当列表滚动时,包裹在RepaintBoundary中的item可以避免重绘,当item重绘的开销特别小时(比如一个颜色块,一个较短的文本),不添加RepaintBoundary反而更高效。

若禁用addAutomaticKeepAlivesaddRepaintBoundaries,会在一定程度上优化内存,但是这会影响渲染性能,需要在内存和渲染性能之间权衡。

5.列表中的元素尽可能使用const修饰

使用 const 相当于将元素缓存起来实现共用,若列表元素某些部分一直保持不变,那么可以使用 const 修饰。

二.滚动优化

1.指定列表项的固定高度

ListViewitemExtent属性用于指定item的固定高度,它告诉ListView在构建列表时使用固定大小的缓冲区。

如果知道item的固定高度,可以讲itemExtent设置为该值,有利于Flutter更有效的管理列表的布局,并且在滚动时可以提高性能

2.合理使用缓冲区

ListView可以通过设置cacheExtent来设置预先加载的内容大小。通过预先加载可以提升view渲染的速度。但是这个值需要合理设置,并非越大越好。因为预加载缓存越大,对页面整体内存的压力就越大。

三.渲染优化

1.setState状态刷新位置尽量放置于视图树的低层级,推荐使用Selector构建需要刷新的组件,以维持最小刷新范围。

2.对于频繁更新的控件(如动画),使用RepaintBoundary隔离它,创建单独layer减少重绘区域。

3.使用图片替换半透明效果。

4.减少SaveLayer(ShaderMaskColorFilterText Overflow)、ClipPath的使用,提高渲染线程性能。

5.避免使用Opacity widget,尤其是在动画中避免使用,用AnimatedOpacityFadeInImage进行代替。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容