从listView.builder删除项目始终删除最后一项

发布于 2025-01-22 01:46:34 字数 6010 浏览 0 评论 0原文

当我尝试删除项目时,每次最后一项都会被删除。在搜索解决方案后,我发现它使用已有的窗口小部件来使用,而解决方案是在小部件中添加键。

所以我添加了钥匙,但问题还没有消失。 最后一项仍然被删除。 波纹管,我试图表现出尽可能详细的情况。最后,您会看到,当我以索引(0)删除该项目时,它被调用,但索引(1)被从UI处置。但是在列表中,第一个项目被正确删除了。

这是listView.builder

                     ListView.builder(
                        primary: false,
                        shrinkWrap: true,
                        scrollDirection: Axis.vertical,
                        physics: const NeverScrollableScrollPhysics(),
                        itemCount: saleItems.length,
                        itemBuilder: (BuildContext context, int index) {
                          print('Value key: ${ValueKey(index)}');
                          return ProductItemWidget(
                            key: ValueKey(index),
                            itemContext: context,
                            mainItems: batches,
                            onDelete: () {
                              setState(() {
                                saleItems.remove(saleItems[index]);
                                print(
                                    'deleted $index - value ${ValueKey(index)}');
                                print(saleItems);
                              });
                            },
                            onNewSaleItem: (newItem) {
                              setState(() {
                                saleItems[index] = newItem;
                              });
                              print(saleItems);
                            },
                          );
                        },
                      ),

将新项目添加到列表

SizedBox(
                        key: _addButtonKey,
                        child: KFilledButton(
                          text: 'New Sale Item',
                          onPressed: () {
                            setState(() {
                              saleItems.add(newSaleItemModal);
                            });
                            scrollToAddButton();
                          },
                        ),
                      ),

该项目的实例和列表

  NewSaleItemModal newSaleItemModal = NewSaleItemModal();
  List<NewSaleItemModal> saleItems = [];

ProductItemwidget()页

这是构造函数

class ProductItemWidget extends StatefulWidget {
  void Function() onDelete;
  List<dynamic>? mainItems;
  BuildContext? itemContext;
  Function(NewSaleItemModal newSaleItem) onNewSaleItem;
  ProductItemWidget({
    Key? key,
    required this.onDelete,
    required this.onNewSaleItem,
    this.mainItems,
    this.itemContext,
  }) : super(key: key);

  @override
  State<ProductItemWidget> createState() => _ProductItemWidgetState();
}

这些是状态

  @override
  void initState() {
    super.initState();
    print('Created with key: ${widget.key}');
  }

  @override
  void didChangeDependencies() {
    types = profileRepository.getConfigEnums(type: EnumType.discountType);
    getAllProductNames();
    super.didChangeDependencies();
  }

  @override
  void dispose() {
    super.dispose();
    print('Disposed key: ${widget.key}');
    selectedProductName = null;
    selectedProduct = null;
    selectedType = null;
    _discountController.dispose();
    _rateController.dispose();
    _quantityController.dispose();
    _unitController.dispose();
    _amountController.dispose();
  }

这是我添加键

的地方
 @override
  Widget build(BuildContext itemContext) {
    return Form(
      key: widget.key,
      child: ..........
      ),
     }

“添加第一个项目”

添加第一个项目后,在控制台...

I/flutter (17380): Value key: [<0>]
I/flutter (17380): Created with key: [<0>]
I/flutter (17380): [NewSaleItemModal(productId: 23, batchId: 88, rate: 35567, quantity: 1, unitId: 1, discount: 0, discountType: null, amount: 35567)]

“添加第二个项目”

添加第二项后,在控制台...

I/flutter (17380): Value key: [<1>]
I/flutter (17380): Created with key: [<1>]
I/flutter (17380): [NewSaleItemModal(productId: 23, batchId: 88, rate: 35567, quantity: 1, unitId: 1, discount: 0, discountType: null, amount: 35567), NewSaleItemModal(productId: 4, batchId: 69, rate: 1158, quantity: 1, unitId: 1, discount: 0, discountType: null, amount: 1158)]

这是视频删除第一个项目

当我删除第一个项目时,在控制台...

I/flutter (17380): deleted 0 - value [<0>]
I/flutter (17380): [NewSaleItemModal(productId: 4, batchId: 69, rate: 1158, quantity: 1, unitId: 1, discount: 0, discountType: null, amount: 1158)]

I/flutter (17380): Value key: [<0>]
I/flutter (17380): Disposed key: [<1>]

When I tried to remove an item, every time the last item get removed. After searching for solutions, I found out it works this way with stateful widgets, and the solution is to add keys in the widgets.

So I added keys but the problem isn't gone. The last item still gets removed.
Bellow, I tried to show the situation as detailed as possible. At the very last, you will see, when I remove the item at index(0) it gets called but index(1) gets disposed from the UI. But in the list, the 1st item got removed properly.

This is the ListView.builder

                     ListView.builder(
                        primary: false,
                        shrinkWrap: true,
                        scrollDirection: Axis.vertical,
                        physics: const NeverScrollableScrollPhysics(),
                        itemCount: saleItems.length,
                        itemBuilder: (BuildContext context, int index) {
                          print('Value key: ${ValueKey(index)}');
                          return ProductItemWidget(
                            key: ValueKey(index),
                            itemContext: context,
                            mainItems: batches,
                            onDelete: () {
                              setState(() {
                                saleItems.remove(saleItems[index]);
                                print(
                                    'deleted $index - value ${ValueKey(index)}');
                                print(saleItems);
                              });
                            },
                            onNewSaleItem: (newItem) {
                              setState(() {
                                saleItems[index] = newItem;
                              });
                              print(saleItems);
                            },
                          );
                        },
                      ),

Adding new items to the list

SizedBox(
                        key: _addButtonKey,
                        child: KFilledButton(
                          text: 'New Sale Item',
                          onPressed: () {
                            setState(() {
                              saleItems.add(newSaleItemModal);
                            });
                            scrollToAddButton();
                          },
                        ),
                      ),

Instance of the item and the list

  NewSaleItemModal newSaleItemModal = NewSaleItemModal();
  List<NewSaleItemModal> saleItems = [];

ProductItemWidget() page

This is the Constructor

class ProductItemWidget extends StatefulWidget {
  void Function() onDelete;
  List<dynamic>? mainItems;
  BuildContext? itemContext;
  Function(NewSaleItemModal newSaleItem) onNewSaleItem;
  ProductItemWidget({
    Key? key,
    required this.onDelete,
    required this.onNewSaleItem,
    this.mainItems,
    this.itemContext,
  }) : super(key: key);

  @override
  State<ProductItemWidget> createState() => _ProductItemWidgetState();
}

These are the states

  @override
  void initState() {
    super.initState();
    print('Created with key: ${widget.key}');
  }

  @override
  void didChangeDependencies() {
    types = profileRepository.getConfigEnums(type: EnumType.discountType);
    getAllProductNames();
    super.didChangeDependencies();
  }

  @override
  void dispose() {
    super.dispose();
    print('Disposed key: ${widget.key}');
    selectedProductName = null;
    selectedProduct = null;
    selectedType = null;
    _discountController.dispose();
    _rateController.dispose();
    _quantityController.dispose();
    _unitController.dispose();
    _amountController.dispose();
  }

This is the where I added the key

 @override
  Widget build(BuildContext itemContext) {
    return Form(
      key: widget.key,
      child: ..........
      ),
     }

After adding first item

After adding first item, in console...

I/flutter (17380): Value key: [<0>]
I/flutter (17380): Created with key: [<0>]
I/flutter (17380): [NewSaleItemModal(productId: 23, batchId: 88, rate: 35567, quantity: 1, unitId: 1, discount: 0, discountType: null, amount: 35567)]

After adding second item

After adding second item, in console...

I/flutter (17380): Value key: [<1>]
I/flutter (17380): Created with key: [<1>]
I/flutter (17380): [NewSaleItemModal(productId: 23, batchId: 88, rate: 35567, quantity: 1, unitId: 1, discount: 0, discountType: null, amount: 35567), NewSaleItemModal(productId: 4, batchId: 69, rate: 1158, quantity: 1, unitId: 1, discount: 0, discountType: null, amount: 1158)]

Here is the video deleting the first item

When i delete the first item, in console...

I/flutter (17380): deleted 0 - value [<0>]
I/flutter (17380): [NewSaleItemModal(productId: 4, batchId: 69, rate: 1158, quantity: 1, unitId: 1, discount: 0, discountType: null, amount: 1158)]

I/flutter (17380): Value key: [<0>]
I/flutter (17380): Disposed key: [<1>]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

横笛休吹塞上声 2025-01-29 01:46:34

嗯,尝试使用删除位置来识别要删除的项目

saleItems.removeWhere((e)=> e.productId == saleItems[index].productId);

hmm try using removeWhere to identify which item to be remove

saleItems.removeWhere((e)=> e.productId == saleItems[index].productId);
绿光 2025-01-29 01:46:34

只需使用unique key()而不是valuekey(index)
它似乎已经为我解决了问题。

Just use UniqueKey() instead of ValueKey(index)
It seems to have solved the problem for me.

裸钻 2025-01-29 01:46:34

我在两个不同的项目中也遇到了同样的问题,有时甚至应用了一个“解决方法”解决方案,例如可见性(可见:!_isdeleted,Child:myListViewItem(...),但我总是最终出现采用相同的方法:

管理库,例如scopedmodel,redux或bloc

使用状态

  • 。事实来源“
  • 您所有的listView项目都只是“轻巧”的小部件,
  • 一旦您要更新=&gt;仅更新模型,并且所有ListView项目都会绘制任何内容是否需要
  • 删除
  • ? 这不应阻止您。

数字框等。

I also had the same problem in two my different projects, and sometimes even applied a "workaround" solution, like Visibility(visible: !_isDeleted, child: MyListViewItem(...) but I always ended up with the same approach:

Use state management libraries. E.g. ScopedModel, Redux or Bloc. This appeared to be the only correct way for me.

In a few words:

  • Create a "model" that is always a "source of truth"
  • All your listView items are just "lightweight" widgets that "reflect" the model (no matter stateful or stateless they are)
  • Once you want to update => update only the model, and all listView items will draw whatever the model wants
  • Want to delete? Just define and call model.removeItemAt(i). All listView items will be rebuilt properly
  • There will be some minor "issues" with updating widgets with user input, like text fields, numeric boxes, etc. This should not stop you. Define TextEditingControllers for all text fields and update the model each time user changes the text

I hope it will help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文