Flutter Riverpod:如何在Slivers中使用Consumer并按列表项返回多组Sliver组件
实现方案
你当前的核心限制是Consumer作为CustomScrollView的slivers数组的子项,必须返回单个Sliver类型组件,而你需要为每个record返回两个Sliver(SliverPersistentHeader + SliverList),所以有两种常用实现方案:
方案1:使用官方SliverMainAxisGroup打包(推荐,Flutter 3.13+支持)
Flutter 3.13新增了SliverMainAxisGroup组件,支持将多个Sliver合并为单个Sliver返回,无需修改现有代码结构,实现如下:
@override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( slivers: <Widget>[ const SliverToBoxAdapter(), Consumer( builder: (context, watch, child) { return watch(recordProvider).when( data: (records) { // 遍历record生成每组Sliver,再拍平为一维数组传给SliverMainAxisGroup return SliverMainAxisGroup( slivers: records.map((record) { return [ // 自定义的分组头部 SliverPersistentHeader( pinned: true, delegate: _YourHeaderDelegate(record: record), ), // 分组对应的列表 SliverList( delegate: SliverChildBuilderDelegate( (context, index) => _YourListItemWidget(item: record.items[index]), childCount: record.items.length, ), ) ]; }).expand((widgetList) => widgetList).toList(), ); }, loading: () => const SliverToBoxAdapter(), error: (obj, error) => const SliverToBoxAdapter(), ); }, ), const SliverToBoxAdapter(), ], ), ); }
方案2:外层套Consumer(全版本兼容)
如果你的Flutter版本低于3.13,无法使用SliverMainAxisGroup,可以把Consumer提到CustomScrollView外层,通过展开运算符直接把生成的Sliver列表插入到slivers数组中,实现如下:
@override Widget build(BuildContext context) { return Scaffold( // Consumer提到外层包裹CustomScrollView body: Consumer( builder: (context, watch, child) { final recordState = watch(recordProvider); return CustomScrollView( slivers: <Widget>[ const SliverToBoxAdapter(), // 用展开运算符直接插入生成的Sliver数组 ...recordState.when( data: (records) { return records.map((record) { return [ SliverPersistentHeader( pinned: true, delegate: _YourHeaderDelegate(record: record), ), SliverList( delegate: SliverChildBuilderDelegate( (context, index) => _YourListItemWidget(item: record.items[index]), childCount: record.items.length, ), ) ]; }).expand((widgetList) => widgetList).toList(); }, loading: () => [const SliverToBoxAdapter()], error: (obj, error) => [const SliverToBoxAdapter()], ), const SliverToBoxAdapter(), ], ); }, ), ); }
补充说明
- 若你使用的是Riverpod 2.x版本,需要将代码中
builder的参数watch替换为ref,调用方式改为ref.watch(recordProvider) - 你需要自行实现继承自
SliverPersistentHeaderDelegate的头部代理类,完成SliverPersistentHeader的布局逻辑 - 如果你不需要单独的列表懒加载,也可以把
SliverList替换为SliverToBoxAdapter等其他Sliver组件
内容的提问来源于stack exchange,提问作者Answer_K
相关产品推荐
相关产品推荐

