Sliver 为什么能天然缩小 rebuild 影响面



子玥酱 (掘金 / 知乎 / 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 的"天然边界感"

SliverChildBuilderDelegateListView.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 给你的,不是性能魔法,而是一种更接近底层真实模型的表达方式

相关推荐
向哆哆4 小时前
打造高校四六级报名管理系统:基于 Flutter × OpenHarmony 的跨端开发实践
flutter·开源·鸿蒙·openharmony·开源鸿蒙
2501_940007894 小时前
Flutter for OpenHarmony三国杀攻略App实战 - 设置功能实现
flutter
lbb 小魔仙5 小时前
【Harmonyos】开源鸿蒙跨平台训练营DAY9:获取分类数据并渲染
flutter·华为·harmonyos
mocoding5 小时前
Flutter 3D 翻转动画flip_card三方库在鸿蒙版天气预报卡片中的实战教程
flutter·3d·harmonyos
2601_949809597 小时前
flutter_for_openharmony家庭相册app实战+我的Tab实现
java·javascript·flutter
2601_949868367 小时前
Flutter for OpenHarmony 电子合同签署App实战 - 已签合同实现
java·开发语言·flutter
我真的是大笨蛋8 小时前
深度解析InnoDB如何保障Buffer与磁盘数据一致性
java·数据库·sql·mysql·性能优化
一起养小猫8 小时前
Flutter for OpenHarmony 实战:别踩白方块游戏完整开发指南
flutter·游戏
●VON9 小时前
Flutter for OpenHarmony 21天训练营 Day03 总结:从学习到输出,迈出原创第一步
学习·flutter·openharmony·布局·技术
程序员清洒9 小时前
Flutter for OpenHarmony:Text — 文本显示与样式控制
开发语言·javascript·flutter