Flutter Riverpod:如何在 slivers 中使用消费者小部件

Flutter Riverpod : how to use consumer widget in slivers

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          const SliverToBoxAdapter(),
          Consumer(
            builder: (context, watch, child) {
              return watch(recordProvider).when(
                data: (records) {
                  // how to returns a set of Weigets(SliverPersistentHeader and SliverList) based on each item of records, 
                }, 
                loading: () => const SliverToBoxAdapter(),
                error: (obj, error) => const SliverToBoxAdapter(),
              );
            },
          ),
          const SliverToBoxAdapter(),
        ],
      ),
    );
  }
}

刚接触flutter,想知道如何returns根据List中的每条记录生成一组weigets(SliverPersistentHeader and SliverList)?谢谢!

您好,欢迎来到 Flutter。 Slivers 比使用其他更高级别的小部件要复杂得多,所以我对这个答案一无所知。该代码记录了正在发生的事情,它使用非常原始的数据列表来构建 CustomScrollView,只是一个 List<int>.

/// fake FutureProvider
final recordProvider = FutureProvider(
  (ref) => Future.value(
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
  ),
);

/// Our page of records
class RecordPage extends StatelessWidget {
  const RecordPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Consumer(
        builder: (context, watch, child) {
          /// Building a list of our slivers up front so that it's easier to read
          final List<Widget> slivers = watch(recordProvider).when(
            data: (records) {
              /// Lets split up some data so we can have our persistent headers hold some lists
              final even = records.where((element) => element & 1 == 0);
              final odd = records.where((element) => element & 1 == 1);

              /// Now we need to take that data and make some lists of widgets
              final evenWidgets =
                  even.map((e) => RecordWidget(record: e)).toList();
              final oddWidgets =
                  odd.map((e) => RecordWidget(record: e)).toList();

              /// Now let's make some SliverLists
              final evenSliverList = SliverList(
                delegate: SliverChildListDelegate.fixed(evenWidgets),
              );
              final oddSliverList = SliverList(
                delegate: SliverChildListDelegate.fixed(oddWidgets),
              );

              /// Now let's create some headers
              const evenHeader = SliverPersistentHeader(
                delegate: RecordPersistentHeader('Even'),
              );

              const oddHeader = SliverPersistentHeader(
                delegate: RecordPersistentHeader('Odd'),
              );

              /// Now let's merge them all together and return the slivers
              return [
                evenHeader,
                evenSliverList,
                oddHeader,
                oddSliverList,
              ];
            },
            loading: () => [const SliverToBoxAdapter()],
            error: (obj, error) => [const SliverToBoxAdapter()],
          );

          /// Finally let's return our [CustomScrollView] with our list of slivers
          return CustomScrollView(
            slivers: slivers,
          );
        },
      ),
    );
  }
}

/// The contents of our record sliver
class RecordWidget extends StatelessWidget {
  const RecordWidget({Key? key, required this.record}) : super(key: key);

  final int record;

  @override
  Widget build(BuildContext context) {
    return Text('$record');
  }
}

/// The contents of our header sliver
class RecordPersistentHeader extends SliverPersistentHeaderDelegate {
  const RecordPersistentHeader(this.title);

  final String title;

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return Text(title);
  }

  @override
  double get maxExtent => 40;

  @override
  double get minExtent => 40;

  @override
  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
    return false;
  }
}