我的目标是在按下“ float 操作”按钮时能够将“虚拟” ListTiles添加到ListView。
class Notes extends StatefulWidget{
_NotesState createState() => new _NotesState();
}
class _NotesState extends State<Notes>{
List<ListTile> notes =[];
void addNewNote(){
setState((){
notes.add(new ListTile(title: new Text("Broccolli")));
}
@override
Widget build(BuildContext context){
return new Scaffold(
appBar: new AppBar(title: "NOTES"),
body: new Stack(
children: <Widget>[
// The notes
new Container(
child: new ListView(
children: notes,
)
),
// The add notes button
new FloatingActionButton(
tooltip: 'Add a note',
onPressed: addNewNote,
)
],
),
);
}
}
当我按Floating Action Button时,新的ListTile将添加到列表中,但ListView不会更新。我想我想念/错过了一个基本概念。
最佳答案
最大的问题是您要直接将小部件列表作为Notes的子级传递。当Flutter进行重建时,它会查看所有小部件并检查它们是否已更改;然后,它仅传播已更改的更改城镇分支。
因为您要传递完全相同的列表,而flutter喜欢以一种优化的方式执行操作,所以它仅检查ListView的子级列表是否是完全相同的列表-并且由于您每次都传递相同的列表,因此不会看不到区别。
一种选择是,您每次都可以简单地重新创建一个新列表(通过将notes
包装在new List.from(notes, growable: false)
中。但是这种错漏了点。
您的窗口小部件应该仅存储创建窗口小部件所需的信息,然后才应在build
函数中完成窗口小部件的实际创建。
这样看起来像这样:
class Notes extends StatefulWidget {
_NotesState createState() => new _NotesState();
}
class _NotesState extends State<Notes> {
List<String> notes = [];
void addNewNote() {
setState(() {
notes.add("Broccolli ${notes.length}");
});
}
@override
Widget build(BuildContext context) {
print("Notes: $notes");
return new Scaffold(
appBar: new AppBar(title: new Text("NOTES")),
body: new Stack(
children: <Widget>[
// The notes
new Container(
child: new ListView(
children: notes
.map((string) => new ListTile(title: new Text(string)))
.toList(growable: false)),
),
// The add notes button
new FloatingActionButton(
tooltip: 'Add a note',
onPressed: addNewNote,
)
],
),
);
}
}
直接存储listTiles确实可以工作,但是如果您开始拥有更复杂的小部件(特别是有状态小部件),则很可能不会。
关于dart - 一个如何更新ListView子级?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49676360/