I want to update my ListView if i remove or add items. Right now i just want to delete items and see the deletion of the items immediately.
My application is more complex so i wrote a small example project to show my problems.
The TestItem
class holds some data entries:
class TestItem {
static int id = 1;
bool isFinished = false;
String text;
TestItem() {
text = "Item ${id++}";
}
}
The ItemInfoViewWidget
is the UI representation of the TestItem
and removes the item if it is finished (whenever the Checkbox is changed to true).
class ItemInfoViewWidget extends StatefulWidget {
TestItem item;
List<TestItem> items;
ItemInfoViewWidget(this.items, this.item);
@override
_ItemInfoViewWidgetState createState() =>
_ItemInfoViewWidgetState(this.items, this.item);
}
class _ItemInfoViewWidgetState extends State<ItemInfoViewWidget> {
TestItem item;
List<TestItem> items;
_ItemInfoViewWidgetState(this.items, this.item);
@override
Widget build(BuildContext context) {
return new Card(
child: new Column(
children: <Widget>[
new Text(this.item.text),
new Checkbox(
value: this.item.isFinished, onChanged: isFinishedChanged)
],
),
);
}
void isFinishedChanged(bool value) {
setState(() {
this.item.isFinished = value;
this.items.remove(this.item);
});
}
}
The ItemViewWidget
class builds the ListView
.
class ItemViewWidget extends StatefulWidget {
List<TestItem> items;
ItemViewWidget(this.items);
@override
_ItemViewWidgetState createState() => _ItemViewWidgetState(this.items);
}
class _ItemViewWidgetState extends State<ItemViewWidget> {
List<TestItem> items;
_ItemViewWidgetState(this.items);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: new Text('Test'),
),
body: ListView.builder(
itemCount: this.items.length,
itemBuilder: (BuildContext context, int index) {
return new ItemInfoViewWidget(this.items, this.items[index]);
}),
);
}
}
The MyApp
shows one TestItem
and a button that navigates to the ItemViewWidget
page.
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
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> {
int _counter = 0;
List<TestItem> items = new List<TestItem>();
_MyHomePageState() {
for (int i = 0; i < 20; i++) {
this.items.add(new TestItem());
}
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Column(
children: <Widget>[
ItemInfoViewWidget(this.items, this.items.first),
FlatButton(
child: new Text('Open Detailed View'),
onPressed: buttonClicked,
)
],
));
}
void buttonClicked() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ItemViewWidget(this.items)),
);
}
}
If i toggle the Checkbox of the first item, the Checkbox is marked as finished (as expected), but it is not removed from the UI - however it is removed from the list.
Then I go back to the Main page and I can observe that Item 1 is checked there as well.
So if I go to the ItemViewWidget
page again, I can observe that the checked items are no longer present.
Based on these observations, I come to the conclusion that my implementation works, but my UI is not updating.
How can I change my code to make an immediate update of the UI possible?
Edit: This is not a duplicate, because
- I dont want to create a new instance of my list just to get the UI updated.
- The answer does not work: I added
this.items = List.from(this.items);
but the behavior of my app is the same as already described above.
- I don't want to break my reference chain by calling
List.from
, because my architecture has one list that is referenced by several classes. If i break the chain i have to update all references by my own. Is there a problem with my architecture?
See Question&Answers more detail:
os