Flutter瀑布流及通用列表解决方案

Posted 闲鱼技术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter瀑布流及通用列表解决方案相关的知识,希望对你有一定的参考价值。

背景

目前闲鱼业务中无论是首页还是搜索页都有大量可以落地瀑布流的场景,而在Flutter原生中只提供了ListView, GridView,无法提供自定义布局的能力。

而在社区中,一般瀑布流的解决方案都是基于SliverMultiBoxAdaptor对其performLayout进行定制,主要存在的问题是缺乏复用机制,并且在很多情形下容易出现重复布局,在线上业务的复杂场景下容易出现帧数偏低的问题, 闪屏的问题。同时对于Child生命周期,打点曝光等一系列基础功能的支持还是一片空白的状态。

所以,我们迫切需要一个更为通用的可以解决复杂布局过程同时能够对基础能力进行扩充的列表视图解决方案。

Flutter中的列表视图介绍

Scrollable

Scrollable是一个StatefulWidget, 职责是监听用户的手势输入。其State的build方法会返回一个含有Listener和RawGestureDetector的Viewport。ScrollPosition用于描述其位置信息,并在其内部定义了 onStart, onUpdate, onEnd等回调。Scrollable中的每一次滑动的开始到结束都对应于一个Darg对象,并且会发送滑动的通知。而Viewport则负责对通知进行监听。

Sliver 

Flutter有两种布局体系 Box, Sliver。在layout的过程中,每个Sliver 都接收 SliverConstraints 计算返回一个 SliverGeometry,可以类比于RenderBox 接收 BoxConstraints 返回一个 Size。Sliver由Viewport统一来负责进行管理。

Viewport

A widget that is bigger on the inside.

Viewport持有一个或多个Sliver。Scrollable将offset传递给Viewport, 由Viewport决定哪些Sliver应该是Visible。Viewport本质上是一个MultiChildRenderObjectWidget,也就是整个滚动视图的主要渲染逻辑都在Viewport中完成。

而在performLayout中,_attemptLayout会以center为中心,先布局leading方向的child,再布局trailing方向的child。其中只有dirty的child会被布局。

 
   
   
 
  1. do{

  2. correction = _attemptLayout(mainAxisExtent, crossAxisExtent, offset.pixels + centerOffsetAdjustment);

  3. if(correction != 0.0) {

  4. offset.correctBy(correction);

    } else{

  5. if(offset.applyContentDimensions(

  6. math.min(0.0, _minScrollExtent + mainAxisExtent * anchor),

  7. math.max(0.0, _maxScrollExtent - mainAxisExtent * (1.0- anchor)),

  8. ))

  9. break;

  10. }

  11. count += 1;

  12. } while(count < _maxLayoutCycles);

如果attemptLayout返回了一个非0的correction, 就会打断当前布局的过程,需要对offset进行调整后重新开始布局,最多只能连续打断10次(maxLayoutCycles)。

correction用于调整,举个

以上是关于Flutter瀑布流及通用列表解决方案的主要内容,如果未能解决你的问题,请参考以下文章

Flutter Weekly Issue 65

JS实现动态瀑布流及放大切换图片效果(js案例)

Flutter最酷炫瀑布流实现

Flutter最酷炫瀑布流实现

Flutter自适应瀑布流

错误记录Flutter 混合开发获取 BinaryMessenger 报错 ( FlutterActivityAndFragmentDelegate.getFlutterEngine() )(代码片段