简介
SliverList 是 CustomScrollView 中用于显示列表的组件,它可以根据需要动态创建子项,实现高效的列表渲染。与普通的 ListView 不同,SliverList 必须在 CustomScrollView 中使用。
基本用法
SliverList(
// 通过 delegate 来构建列表项
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
height: 50,
color: Colors.primaries[index % Colors.primaries.length],
child: Center(
child: Text('Item $index'),
),
);
},
// 列表项数量
childCount: 20,
),
)
代理类型
SliverChildBuilderDelegate
适用于动态创建子项的场景,性能较好。
SliverChildBuilderDelegate(
(BuildContext context, int index) {
return ListTile(
title: Text('Item $index'),
);
},
childCount: 100,
)
SliverChildListDelegate
适用于固定数量的子项列表,所有子项都会一次性创建。
SliverChildListDelegate([
ListTile(title: Text('Item 1')),
ListTile(title: Text('Item 2')),
ListTile(title: Text('Item 3')),
])
常用属性
addAutomaticKeepAlives
是否将列表项保持在内存中,默认为 true。
addRepaintBoundaries
是否为每个列表项添加重绘边界,默认为 true。
addSemanticIndexes
是否添加语义索引,用于无障碍功能,默认为 true。
使用场景
- 在 CustomScrollView 中创建列表
- 需要与其他 Sliver 组件配合使用时
- 实现复杂的滚动效果时
完整示例
class SliverListDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
// 头部
SliverAppBar(
title: Text('SliverList Demo'),
floating: true,
),
// 列表内容
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
// 构建列表项
return Card(
margin: EdgeInsets.all(8.0),
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.primaries[index % Colors.primaries.length],
child: Text('${index + 1}'),
),
title: Text('Item ${index + 1}'),
subtitle: Text('This is item number ${index + 1}'),
trailing: Icon(Icons.arrow_forward_ios),
onTap: () {
// 点击事件处理
print('Tapped item ${index + 1}');
},
),
);
},
// 设置列表项数量
childCount: 50,
),
),
],
),
);
}
}
进阶用法
1. 添加分割线
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
if (index.isOdd) {
return Divider(); // 添加分割线
}
return ListTile(
title: Text('Item ${index ~/ 2}'),
);
},
childCount: 41, // 20个项目加上21个分割线
),
)
2. 实现不同类型的列表项
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
// 根据索引返回不同类型的列表项
if (index % 3 == 0) {
return Container(
height: 100,
color: Colors.blue[100],
child: Center(child: Text('Header $index')),
);
} else {
return ListTile(
title: Text('Item $index'),
);
}
},
childCount: 30,
),
)
性能优化建议
- 优先使用 SliverChildBuilderDelegate 而不是 SliverChildListDelegate
- 合理设置 addAutomaticKeepAlives 和 addRepaintBoundaries
- 避免在构建方法中进行耗时操作
- 使用 const 构造函数来优化重建性能
注意事项
- SliverList 必须在 CustomScrollView 中使用
- 注意内存管理,不要创建过多的列表项
- 合理使用 childCount 属性,避免无限列表导致的性能问题
- 需要处理好列表项的状态管理
实战案例:把多段页面合成一次滚动,SliverList 是粘合剂
之前写多段式页面时吃过亏:SingleChildScrollView 包 Column,里面再塞一个 shrinkWrap 的 ListView——内外两套滚动物理打架,内容一多就卡。改成 CustomScrollView 之后,SliverAppBar 管头部、SliverList 管列表,一套滚动物理,瞬间顺滑。取舍点在于:SliverList 必须活在 CustomScrollView 里,单用它没有意义;delegate 一律用 SliverChildBuilderDelegate 按需构建,SliverChildListDelegate 全量构建只适合固定少量子项。还有个好消息是分页逻辑不用重写:GetX 三件套里分页本来就写在 controller.dart,视图层从 ListView 换成 CustomScrollView 加 SliverList,controller 一行不动。电商 App 的 pull_to_refresh 分页也是这个思路:分页是数据层的事,SliverList 只是换了个懒加载的壳。
参考:Flutter 官方文档(api.flutter.dev)SliverList 类。
总结
SliverList 是 Flutter 中用于创建高性能列表的重要组件,通过合理配置和优化可以实现流畅的列表滚动效果。在使用时需要注意性能优化和内存管理。
