Search code examples
androidflutterlistviewdartandroid-contentprovider

How to use ListView builder with Providers?


I am trying to create Horizontal scrollable cards using ListView Builder and Provider.

Like this one

Is there any other way that I can achieve the same result?

And it says

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ The following ProviderNotFoundError was thrown building BookTile(dirty): Error: Could not find the correct Provider above this BookTile Widget

To fix, please:

  • Ensure the Provider is an ancestor to this BookTile Widget
  • Provide types to Provider
  • Provide types to Consumer
  • Provide types to Provider.of()
  • Always use package imports. Ex: `import 'package:my_app/my_code.dart';
  • Ensure the correct context is being used.

My code

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/files.dart';
import 'bookitem.dart';

class BookTile extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final booksData = Provider.of<Files>(context);
    final books = booksData.items;

    return ListView.builder(
      scrollDirection: Axis.horizontal,
      itemCount: books.length,
      itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
        value: books[i],
        child: BookItem(),
      ),
    );
  }
}

class BookItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final book = Provider.of<File>(context);
    return Container(
      width: 120,
      color: Colors.transparent,
      margin: EdgeInsets.only(right: 20),
      child: Card(
        child: Wrap(
          children: <Widget>[
            Image.network(book.cover),
            Container(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Text(
                    '${book.completion} %',
                    style: TextStyle(
                        color: Colors.black.withOpacity(0.5), fontSize: 12.4),
                  ),
                  IconButton(
                      icon: Icon(
                        Icons.more_horiz,
                        size: 14.5,
                      ),
                      onPressed: null)
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Solution

  • This is not exactly your code, but you will get the idea

    // provider with ChangeNotifier      
    List<Client>? _clients = [];
    
      get clients => _clients;
    
      addClient(Client client) async {
        _clients!.add(client);
        notifyListeners();
      }
    

    Where you would like to use

    Consumer<ClientProvider>(
              builder: (_, data, __) => Expanded(
                child: ListView.builder(
                  itemCount: data.clients.length,
                  itemBuilder: (context, index) {
                    return ClientRow(data.clients[index]);
                  },)
    
    
    

    here is the sample Im doing now