areiser
areiser

Reputation: 569

Flutter ListView not updating

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),
       );
    }
}

Upvotes: 8

Views: 22364

Answers (4)

MinciLover
MinciLover

Reputation: 21

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())
  );
}),

Upvotes: 0

AnasSafi
AnasSafi

Reputation: 6294

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.

Upvotes: 1

Constantin De La Roche
Constantin De La Roche

Reputation: 3320

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/

Upvotes: 1

areiser
areiser

Reputation: 569

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) {
    ...
  }

Upvotes: 10

Related Questions