flutterriverpod

How Can I use a Riverpod Provider from within a SliverList?


I've got a small Flutter widget that should show a list of items via a Riverpod provider. I'm having a hard time figuring out the proper way to handle the setup. My current code looks like this:

Widget build(BuildContext context, WidgetRef ref) {
    final listValue = ref.watch(listProvider);
    return Scaffold(
      body: CustomScrollView(
        slivers: [
          SliverAppBar...
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) {
                return listValue.when(
                  data: (things) => ListTile(
                    title: things[index].name,
                    subtitle: things[index].date,
                  ),
                  error: (e, st) => SliverToBoxAdapter(
                      child: Center(child: Text('Error! $e'))),
                  loading: () => SliverToBoxAdapter(
                      child: const Center(
                          child: CircularProgressIndicator.adaptive())),
                );
              },
              childCount: // where do I get this? no access to listValue,
          ),
          SliverFillRemaining(),
        ])...

This works, but I get an error below the final list item since there's no childCount...


Solution

  • Extract listvalue.when to the top of the SliverList to get length value inside the Delegate and handle the errors gracefully here is the full code

    Widget build(BuildContext context, WidgetRef ref) {
      final listValue = ref.watch(listProvider);
    
      return Scaffold(
        body: CustomScrollView(
          slivers: [
            SliverAppBar...
            listValue.when(
              data: (things) {
               if(things.isEmpty){
                return SliverToBoxAdapter(
                        child: Center(child: Text("No items available.")),
                      );
                }
               return SliverList(
                        delegate: SliverChildBuilderDelegate(
                          (context, index) => ListTile(
                            title: Text(things[index].name),
                            subtitle: Text(things[index].date),
                          ),
                          childCount: things.length,
                        ),
                      );
              },
              error: (e, st) => SliverToBoxAdapter(
                child: Center(child: Text('Error: $e')),
              ),
              loading: () => const SliverToBoxAdapter(
                child: Center(child: CircularProgressIndicator.adaptive()),
              ),
            ),
    
            const SliverFillRemaining(),
          ],
        ),
      );
    }