DEV Community

David MM👨🏻‍💻
David MM👨🏻‍💻

Posted on

7 1

How to rebuild a ListView on Flutter using Provider async?

TL;DR: My Provider class doesn't trigger a rebuild, but I don't know what I'm doing wrong. Code provided below.

Hi,

I have a ListView.builder nested inside a Consumer.

While it creates as many MyProvider instances I have, if I delete or update an element, it does delete/update that element on the database, but it doesn't trigger a rebuild on the ListView builder, despite using notifyListeners().

This is (a simplified version of) my code:

genre_list.dart

class GenreListScreen extends StatefulWidget {
  static const routeName = '/genre-list';

  @override
  _GenreListScreenState createState() => _GenreListScreenState();
}

class _GenreListScreenState extends State<GenreListScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: ...
      ),
      body: Consumer<GenreProvider>(
        builder: (context, data, index) {
          var genres = data.getGenres;

          return ListView.builder(
            itemCount: genres.length,
            itemBuilder: (context, index) {
              var genre = genres[index];
              return ListTile(
                title: Text(genre['title']),
                subtitle: IconButton(
                  icon: Icon(Icons.edit),
                  onPressed: () async {
                    try {
                      GenreProvider().updateGenre(genre['id'], 'Testing');
                    } on Exception catch (_) {
                      showSnackBar(
                        text: 'Unknown error updating the genre.',
                        color: Colors.red,
                        context: context,
                      );
                    }
                  },
                ),
              );
            },
          );
        },
      ),
    );
  }
}

Enter fullscreen mode Exit fullscreen mode

genre_provider.dart

class GenreProvider with ChangeNotifier {
  static List<Map<String, dynamic>> _genres = [];

  Future fetchGenres() async {
    try {
      QuerySnapshot<Map<String, dynamic>> genres =
          await FirebaseFirestore.instance.collection('genres').get();

      _genres = [];
      genres.docs.forEach((genre) {
        _genres.add({'id': genre.id, 'title': genre['title']});
      });
      notifyListeners();
    } catch (e) {
      print(e);
    }
  }

  Future updateGenre(String id, String title) async {
    try {
      await FirebaseFirestore.instance
          .collection('genres')
          .doc(id)
          .update({'title': title});
      var updatedGenre = _genres.firstWhere((element) => element['id'] == id);
      updatedGenre['title'] = title;
      notifyListeners();
    } catch (e) {
      throw (e);
    }
  }

  List<Map<String, dynamic>> get getGenres {
    return _genres;
  }
}

Enter fullscreen mode Exit fullscreen mode

After a successful login, I call fetchGenres to get the data. Then, I move to GenteListScreen and I can see all the genres I have on my Database.

Clicking on the 'Edit' button, I edit the Genre on the Database (normally a Dialog with a TextFormField, but for the example it is just a fixed string), but it doesn't trigger an UI rebuild on the ListView.

Calling setState(() {}) after the function, triggers a rebuild, and everything is fine, but this call should be done automatically by the Provider package via Consumer.

So the question is: What I am missing on the code to trigger the automatically rebuild?

Sentry blog image

The Visual Studio App Center’s retiring

But sadly….you’re not. See how to make the switch to Sentry for all your crash reporting needs.

Read more

Top comments (1)

Collapse
 
nikolayshtanko profile image
nikolayshtanko • Edited

Hi!, David! I'm sorry for being late :)

You should add wrapper with class "ChangeNotifierProvider" in your widget's tree.
According to this example: flutter.dev/docs/development/data-...

Your should get something like this, I think (in attach image)
dev-to-uploads.s3.amazonaws.com/up...

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay