首页 > 解决方案 > 为什么每次在 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属性更改为ListViewto true)但得到了相同的结果。

标签: listviewdartflutter

解决方案


那是因为您正在更改商品的顺序键。

      ListView(
            children: items,
            reverse: true,
          )

     final listItem = ListItem(key: ValueKey(label), label: label);
        items.add(listItem);

        this.setState(() {
          items = List.from(items);
        });

应该管用


推荐阅读