You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 10:39:04