8

I wanted to create a ListView in Flutter that update when new data arrives. I am using a RefreshIndicator that triggers the list loading for testing. For my list I am using a ListBuilder to map my objects to view objects.

From what I understand, the setState() should trigger an update to my list, however it does not.

Debugging showed that my _listContent is actually filled with 72 items after when the setState() callback is called. Why does my list not auto update? Am I missing something?

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    List<Manga> _listContent = new List<Manga>();

    void _addMangas(List<Manga> mangas) {
      setState(() {
        _listContent.addAll(mangas);
        print('Cleared list');
        });
    }

    Future<Null> _onRefresh() {
      Completer<Null> completer = new Completer<Null>();

      loadMangaItems().then((mangas) => _addMangas(mangas));
      completer.complete();

      return completer.future;
    }

    return new Scaffold(
      appBar: new AppBar(

        title: new Text(widget.title),
      ),
      body: new RefreshIndicator(
          child: new ListView.builder(
              itemCount: _listContent.length,
              itemBuilder: (BuildContext ctx, int index) {
                Manga manga = _listContent[index];
                return new MangaItem(
                  name: manga.writtenName,
                  number: manga.currentNr,
                  state: false,
                );
              }),
          onRefresh: _onRefresh),
       );
    }
}
1
  • 1
    I have a question about this implementation of the RefreshCallback (_onRefresh()). Isn't completer.complete(); being called here before the loadMangaItems() completes? Commented Nov 27, 2017 at 1:34

4 Answers 4

10

Turns out the problem was that

List<Manga> _listContent = new List<Manga>();

was defined on top of widget.build and not on top of the State class. Defining it like this works fine:

class _MyHomePageState extends State<MyHomePage> {
  List<Manga> _listContent = new List<Manga>();

  @override
  Widget build(BuildContext context) {
    ...
  }
Sign up to request clarification or add additional context in comments.

1 Comment

You can also move _addMangas and _onRefresh outside of your build method. There is no reason to have it in there.
1

I solved a similiar issue by calling the setState method (notify the framework that the internal state of this object has changed).

Example here: https://googleflutter.com/flutter-add-item-to-listview-dynamically/

Comments

1

I think who reading this answer try to update all list of ListView lump sum, by replace old list with new one, the problem happen if old list similar to new one in most values, I solved this problem temporarily in the following way:

setState(() => _currentList.clear());
Future.delayed(const Duration(milliseconds: 50), () {
  setState(() => _currentList.addAll(_newList));
});

You can show CircularProgressIndicator during the 50 milliseconds.

Note: if elements of current list are not the same as the elements of the new list and its has completely different, you will not face this problem.

Comments

0

You can use the key for your custom widget, like the following:

itemBuilder: (BuildContext ctx, int index) {
  Manga manga = _listContent[index];
  return new MangaItem(
    name: manga.writtenName,
    number: manga.currentNr,
    state: false,
    key: Key(index.toString())
  );
}),

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.