

子玥酱 (掘金 / 知乎 / CSDN / 简书 同名)
大家好,我是 子玥酱,一名长期深耕在一线的前端程序媛 👩💻。曾就职于多家知名互联网大厂,目前在某国企负责前端软件研发相关工作,主要聚焦于业务型系统的工程化建设与长期维护。
我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括 前端工程化、小程序、React / RN、Flutter、跨端方案,
在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。
技术方向: 前端 / 跨端 / 小程序 / 移动端工程化 内容平台: 掘金、知乎、CSDN、简书 创作特点: 实战导向、源码拆解、少空谈多落地 **文章状态:**长期稳定更新,大量原创输出
我的内容主要围绕 前端技术实战、真实业务踩坑总结、框架与方案选型思考、行业趋势解读 展开。文章不会停留在"API 怎么用",而是更关注为什么这么设计、在什么场景下容易踩坑、真实项目中如何取舍,希望能帮你在实际工作中少走弯路。
子玥酱 · 前端成长记录官 ✨
👋 如果你正在做前端,或准备长期走前端这条路
📚 关注我,第一时间获取前端行业趋势与实践总结
🎁 可领取 11 类前端进阶学习资源 (工程化 / 框架 / 跨端 / 面试 / 架构)
💡 一起把技术学"明白",也用"到位"
持续写作,持续进阶。
愿我们都能在代码和生活里,走得更稳一点 🌱
文章目录
-
- [Sliver 不是"更快的 ListView"](#Sliver 不是“更快的 ListView”)
- [ListView 的真实结构,比你想象得"厚"](#ListView 的真实结构,比你想象得“厚”)
- [ListView 的问题,不在 List,而在"整体感"](#ListView 的问题,不在 List,而在“整体感”)
- [Sliver 的设计,从一开始就不是"整体列表"](#Sliver 的设计,从一开始就不是“整体列表”)
- [Sliver 是如何"切断 rebuild 传播路径"的](#Sliver 是如何“切断 rebuild 传播路径”的)
-
- [在 Sliver 体系里:](#在 Sliver 体系里:)
- 一个最常见的对比例子
-
- [ListView 写法](#ListView 写法)
- [Sliver 写法](#Sliver 写法)
- [SliverChildBuilderDelegate 的"天然边界感"](#SliverChildBuilderDelegate 的“天然边界感”)
- [Sliver + key,对状态边界更友好](#Sliver + key,对状态边界更友好)
- [为什么 Sliver 更"逼你写对"](#为什么 Sliver 更“逼你写对”)
-
- [ListView 很"宽容"](#ListView 很“宽容”)
- [Sliver 很"严格"](#Sliver 很“严格”)
- [Sliver 更适合复杂、长生命周期页面](#Sliver 更适合复杂、长生命周期页面)
- [一个"更安全"的 Sliver 结构示例](#一个“更安全”的 Sliver 结构示例)
- [Sliver 的优势](#Sliver 的优势)
- 总结
很多人在项目里第一次把 ListView 换成 CustomScrollView + SliverList 后,都会有一个共同感受:
好像也没怎么优化,但滚动更稳了。
这背后不是魔法,而是 Flutter 在 Sliver 体系里,换了一种组织渲染的方式。
Sliver 不是"更快的 ListView"
- Sliver ≠ 更快的 ListView
- Sliver ≠ 神奇性能组件
它真正不一样的地方在于:
Sliver 把"滚动上下文"和"内容渲染"彻底拆开了。
ListView 的真实结构,比你想象得"厚"
从源码角度看,一个 ListView 本质上是:
text
Scrollable
└─ Viewport
└─ SliverList
也就是说:
ListView 只是 Sliver 体系的一个"封装版入口"。
那为什么直接用 ListView,rebuild 更容易失控?
ListView 的问题,不在 List,而在"整体感"
ListView 给你的,是一个整体组件的错觉:
dart
ListView.builder(
itemBuilder: ...
)
看起来:
- 这是一个列表
- item 是它的子节点
但在 rebuild 关系上:
ListView 是一个整体 Widget
只要 ListView rebuild:
- Viewport 会重新参与计算
- SliverList 会重新评估
- itemBuilder 可能被重新触发
Sliver 的设计,从一开始就不是"整体列表"
Sliver 的核心思想是:
滚动区域中,每一段内容,都是独立参与布局和渲染的。
来看一个典型结构:
dart
CustomScrollView(
slivers: [
SliverToBoxAdapter(child: Header()),
SliverList(delegate: ...),
SliverToBoxAdapter(child: Footer()),
],
);
这里有一个非常重要的变化:
- Header 是一个 sliver
- List 是一个 sliver
- Footer 也是一个 sliver
它们不是 children,而是:
滚动流中的独立单元
Sliver 是如何"切断 rebuild 传播路径"的
在 Sliver 体系里:
- 每一个 sliver 都有自己的 layout / paint 边界
- Sliver 之间不会互相影响
- rebuild 更容易被限制在 sliver 内部
也就是说:
Header rebuild,不会影响 List 的滚动布局
List 内 item rebuild,不会波及其他 sliver
一个最常见的对比例子
ListView 写法
dart
Column(
children: [
Header(),
Expanded(
child: ListView.builder(
itemBuilder: ...
),
),
],
);
问题在于:
- Column rebuild
- ListView 作为子节点重新 build
- 滚动上下文被整体触发
Sliver 写法
dart
CustomScrollView(
slivers: [
SliverToBoxAdapter(child: Header()),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ItemTile(index: index),
),
),
],
);
这里:
- Header 是独立 sliver
- List 是独立 sliver
- rebuild 的传播路径被切断
SliverChildBuilderDelegate 的"天然边界感"
SliverChildBuilderDelegate 和 ListView.builder 看起来很像,但有一个隐含差异:
它是为"按需生成、按需回收"设计的。
它天然假设:
- child 是不稳定的
- child 会频繁进入/离开视口
- child 必须是可被安全重建的
这反而倒逼你:
- item 写得更轻
- 状态更干净
- 副作用更少
Sliver + key,对状态边界更友好
在 Sliver 场景下,key 的意义会被放大。
dart
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
final item = items[index];
return ItemTile(
key: ValueKey(item.id),
item: item,
);
},
),
);
因为:
- Sliver 会更激进地复用 Element
- key 是你唯一能"声明身份"的方式
没有 key,状态错位的概率会比 ListView 更高。
为什么 Sliver 更"逼你写对"
ListView 很"宽容"
- item 写重了,也能跑
- rebuild 大一点,也不立刻炸
- Debug 下卡,Release 下可能还能接受
Sliver 很"严格"
- item 不干净,马上暴露问题
- 状态放错位置,很快掉帧
- rebuild 边界一眼就能看出来
但这恰恰是它的优势。
Sliver 更适合复杂、长生命周期页面
当你的页面出现以下特征时,Sliver 的优势会越来越明显:
- 多段列表
- Header / Tab / 吸顶
- 局部刷新
- 页面常驻
因为它的结构本身就在表达:
哪些内容在滚动中是独立存在的。
一个"更安全"的 Sliver 结构示例
dart
CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: HeaderView(),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return ItemTile(index: index);
},
childCount: items.length,
),
),
],
);
配合之前讲过的:
- item 自己订阅状态
- sliver 本身不 watch 大模型
rebuild 边界会非常清晰。
Sliver 的优势
Sliver 不是让你"更快",而是让你"更不容易写错"。
它通过结构本身:
- 限制 rebuild 传播
- 切割滚动影响面
- 强化状态边界
总结
很多 Flutter 列表性能问题,并不是你不会优化,而是:
你用的是一个"整体感太强"的容器。
Sliver 给你的,不是性能魔法,而是一种更接近底层真实模型的表达方式。