以 ListView
为例,如上图所示是一个高为 701 的 ListView
,实际布局渲染之后,对于 SliverList
输出的 SliverGeom![](https://www.hualigs.cn/image/61dba891ed8ee.jpg) etry
而言:
- 设定里每个 item 的高度为 114;
scrollExtent
是 2353,也就是整体可滑动距离等于 2353;paintExtent
是 701 , 因为ListView
的Viewport
是 701 ,所以从SliverConstraints
得到的remainingPaintExtent
是 701,所以默认只需要绘制和布局高度为 701 的部分; (因为默认 paintExtent = layoutExtent )- 对 item 多出的蓝色 8-9 部分,这是因为在
SliverConstraints
内会有一个叫remainingCacheExtent
的参数,它表示了需要提前缓存的布局区域, 也就是“预布局”的区域,这个区域默认大小是 defaultCacheExtent= 250.0;
ListView
高度为 701,defaultCacheExtent
为默认的 250,也就是得到第一次需要布局到底部的距离其实为 951,按照每个 item 高度是 114 ,那么其实是有 8.3 个 item 高度,取整数也就是 9 个 item ,最终得到整体需要处理的区域大小为 114 * 9 = 1026 ,在SliverList
内部就是endScrollOffset
参数。
所以根据以上情况,ListView
会输出一个 paintExtent
为 701 ,cacheExtent
为 1026 的 SliverGeometry
。
从这个例子可以看出,RenderSliver
在实现可滑动列表的开销和逻辑上,会比直接使用 RenderBox
好和灵活很多,同时也是为什么 Viewport
里需要使用 RenderSliver
而不是 RenderBox
的原因。
⚠️注意,这里比较容易有一个误区,那就是
ListView
是由Viewport
+Scrollable