Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListView does not refresh whereas attached list does (Flutter)

Tags:

flutter

dart

I'm trying to get familiar with flutter and I'm facing some weird case. I want to build a dynamic ListView where a + button allows to add elements. I wrote the following State code:

class MyWidgetListState extends State<MyWidgetList> {
  List<Widget> _objectList = <Widget>[
    new Text('test'),
    new Text('test')
  ];

  void _addOne() {
    setState(() {
      _objectList.add(new Text('test'));
    });
  }

  void _removeOne() {
    setState(() {
      _objectList.removeLast();
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Column(
      children: <Widget>[
        new ListView(
          shrinkWrap: true,
          children: _objectList
        ),
        new Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new IconButton(
              icon: new Icon(Icons.remove_circle),
              iconSize: 36.0,
              tooltip: 'Remove',
              onPressed: _objectList.length > 2 ? _removeOne : null,
            ),
            new IconButton(
              icon: new Icon(Icons.add_circle),
              iconSize: 36.0,
              tooltip: 'Add',
              onPressed: _addOne,
            )
          ],
        ),
        new Text(_objectList.length.toString())
      ],
    );
  }
}

My problem here is that the ListView is visually stuck with the 2 elements I initialized it with.

Internally the _objectList is well managed. For testing purpose I added a simple Text widget at the bottom that shows the size of the list. This one works fine when I click the Add/Remove buttons and it gets properly refreshed. Am I missing something?

like image 611
maphe Avatar asked Aug 12 '18 22:08

maphe


2 Answers

Flutter is based around immutable data. Meaning that if the reference to an object didn't change, the content didn't either.

The problem is, in your case you always send to ListView the same array, and instead mutate its content. But this leads to ListView assuming the list didn't change and therefore prevent useless render.

You can change your setState to keep that in mind :

setState(() {
  _objectList = List.from(_objectList)
    ..add(Text("foo"));
});
like image 105
Rémi Rousselet Avatar answered Nov 03 '22 05:11

Rémi Rousselet


Another Solution!!

Replace ListView with ListView.builder

Code:

    ListView.builder(
            itemBuilder: (ctx, item) {
              return _objectList[item];
            },
            shrinkWrap: true,
            itemCount: _objectList.length,
          ),

Output:

enter image description here

like image 22
Jitesh Mohite Avatar answered Nov 03 '22 06:11

Jitesh Mohite