0

I have a ListView like this but it isn't updating when the value of "mats" changes. The build function is called every time there is an update of my list of mats. The print shows the correct data but the ListView doesn't update correct. Only the number of items updates correct.

flutter: MATS: [[8163b55b-9a4c-44e8-a95e-064b3f5e8a67, , 26.06.2019, [], 0.00 EUR]] flutter: MATS: [[8163b55b-9a4c-44e8-a95e-064b3f5e8a67, Unnamed, 26.06.2019, [], 0.00 EUR]]

  Widget build(BuildContext context) {
    print('MATS: $mats');
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: mats.length == 0
          ? Center(
              child: Text('Add your first mat to start the party.'),
            )
          : mats != null
              ? ListView.builder(
                  key: Key('matsList'),
                  itemCount: mats?.length ?? 0,
                  itemBuilder: (context, index) {
                    final viewModel = mats[index];
                    return MatCardView(
                      key: Key('viewModel.toString()'),
                      viewModel: viewModel,
                      onSelect: onSelect,
                    );
                  })
              : Container(
                  child: Center(
                    child: Text('No beer mat yet'),
                  ),
                ),
    );
  }


Kevin Lücke
  • 11
  • 1
  • 3
  • Can you also post code? – CopsOnRoad Jun 26 '19 at 18:06
  • This is definitely a duplicate of another question, I'll look for it in a second. But the issue is that you're most likely just modifying the list in `mods` without making a new list. The way flutter checks for modification of an object is to do an == comparison on the members, and modifying a list still leads to oldState.list == newState.list. There's two simple ways to get around it - one is to copy your data to a new list each time (which isn't as bad for performance as it sounds as it simply copies the references), or to add an integer that you increment along with every list change. – rmtmckenzie Jun 26 '19 at 18:13
  • Possible duplicate of [Understanding Flutter Render Engine](https://stackoverflow.com/questions/53467979/understanding-flutter-render-engine). There's a really lengthy description of how that part of flutter works that is an interesting read. – rmtmckenzie Jun 26 '19 at 18:14
  • what do you need `key: Key('viewModel.toString()')` for? – pskink Jun 26 '19 at 18:14
  • Also possible duplicate of https://stackoverflow.com/questions/51931017/update-ui-after-removing-items-from-list/51933147#51933147 – rmtmckenzie Jun 26 '19 at 18:15
  • Modifying the `mods` list is fine, this is not React :) – Gazihan Alankus Jun 26 '19 at 18:45

1 Answers1

3

Your keys are the same for each item. It confuses Flutter, because it uses the key to figure out which UI element was for which widget.

Try changing your keys to a unique value for each list item. Here's one pass towards that goal, maybe this would work:

  Widget build(BuildContext context) {
    print('MATS: $mats');
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: mats.length == 0
          ? Center(
              child: Text('Add your first mat to start the party.'),
            )
          : mats != null
              ? ListView.builder(
                  key: Key('matsList'),
                  itemCount: mats?.length ?? 0,
                  itemBuilder: (context, index) {
                    final viewModel = mats[index];
                    return MatCardView(
                      key: Key("item$index"), // THIS LINE CHANGED
                      viewModel: viewModel,
                      onSelect: onSelect,
                    );
                  })
              : Container(
                  child: Center(
                    child: Text('No beer mat yet'),
                  ),
                ),
    );
  }

Note the only line that changed above. Maybe Key(viewModel.toString()) (without quotes) would also work, but I don't know your implementation of it. You can also try that if this does not work.

Gazihan Alankus
  • 11,256
  • 7
  • 46
  • 57