listview - 为什么每次在 0 索引处插入新项目时都会触发所有列表项的“initState()”方法?
问题描述
我想将新的小部件(StatefulWidget)添加到 ListView 到列表的顶部items.insert(0, listItem)
,但是当我这样做时,列表的所有元素都会再次初始化(initState()
每次都调用钩子)
如果我将项目添加到列表的底部items.add(listItem)
- 一切都按预期工作(initState()
仅在新添加的元素上调用。)
用于演示目的的代码
ListItem 小部件代码
class ListItem extends StatefulWidget {
final String label;
const ListItem({Key key, @required this.label}) : super(key: key);
_ListItemState createState() => _ListItemState();
}
class _ListItemState extends State<ListItem> {
@override
void initState() {
super.initState();
print('initState() ${this.widget.label}');
}
@override
Widget build(BuildContext context) {
return Text(this.widget.label);
}
}
列出小部件代码
添加新元素发生在addItem()
函数内部:
class ItemsList extends StatefulWidget {
State<StatefulWidget> createState() => ItemsListState();
}
class ItemsListState extends State<ItemsList> {
var items = List<ListItem>();
@override
Widget build(BuildContext context) {
return GestureDetector(
child: ListView(children: items),
onTap: addItem);
}
void addItem() {
final label = items.length.toString();
print('Add $label');
final listItem = ListItem(key: ValueKey(label), label: label);
items.insert(0, listItem);
this.setState(() {
items = []..addAll(items);
});
}
}
结果
调用函数 3 次时的控制台输出addItem()
(仅举例):
Add 0
initState() 0
Add 1
initState() 1
initState() 0
Add 2
initState() 2
initState() 1
initState() 0
预期输出,当新项目附加到列表底部时(items.add(listItem)
而不是items.insert(0, listItem)
)
Add 0
initState() 0
Add 1
initState() 1
Add 2
initState() 2
这种情况有什么解决方法吗?我想以前添加的列表项保持旧状态。
我试图将列表视口的轴方向更改为up
(将reverse
属性更改为ListView
to true
)但得到了相同的结果。
解决方案
那是因为您正在更改商品的顺序键。
ListView(
children: items,
reverse: true,
)
和
final listItem = ListItem(key: ValueKey(label), label: label);
items.add(listItem);
this.setState(() {
items = List.from(items);
});
应该管用
推荐阅读
- python - 从 Python 调用 C DLL 函数时出错
- regex - Notepad++ 正则压制,正则查找和替换
- gnuplot - Gnuplot:类似示波器的线条样式?
- javascript - 在 html 内容中显示 html 标签,在 html 中显示 html 代码片段
- r - 带有传单的交互式等值线图不准确地映射数据
- python - 如何将 pd.dataframe 列表导入现有 excel 文件的末尾而不覆盖它
- git - 当重命名文件并使用旧名称创建新文件时,什么工作流程可以缓解 git 合并冲突?
- windows - 尝试设置 Windows Jenkins slave,但找不到可用的“Windows Slave”插件
- html - 我正在尝试制作具有两种不同颜色的警报框。前任。包含图片
- c++ - 线程消息或更好:访问“大师班”中其他班级的成员