7

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),
       );
    }
}
areiser
  • 551
  • 1
  • 5
  • 18
  • 1
    I have a question about this implementation of the RefreshCallback (_onRefresh()). Isn't `completer.complete();` being called here *before* the loadMangaItems() completes? – sidecarcat Nov 27 '17 at 01:34

4 Answers4

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) {
    ...
  }
areiser
  • 551
  • 1
  • 5
  • 18
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/

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.

AnasSafi
  • 5,353
  • 1
  • 35
  • 38
0

You can use key for your custom widget

MinciLover
  • 29
  • 4
  • 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](/help/how-to-answer). – Community Aug 10 '22 at 05:22