简体   繁体   English

如何修复“已关闭的 Dismissible 小部件仍然是树的一部分。” flutter 错误

[英]How to fix "A dismissed Dismissible widget is still part of the tree." error in flutter

I am building a fluter app with dismissible widget, firebase and StreamBuilder and getting following error "A dismissed Dismissible widget is still part of the tree."我正在构建一个带有 dismissible 小部件 firebase 和 StreamBuilder 的 flutter 应用程序,并收到以下错误“A dismissed Dismissible widget is still part of the tree.”

Please find the below code sniped for the same.请找到以下相同的代码。

Expanded(
                  child: StreamBuilder(
                    stream: Firestore.instance
                        .document('/users/User1/Trips/${widget.tripId}')
                        .collection('TropDocs')
                        .snapshots(),
                    builder: (context, snapshot) {
                      if (!snapshot.hasData) return const Text("Loading....");
                      return ListView.builder(
                        itemExtent: 150.0,
                        itemCount: snapshot.data.documents.length,
                        itemBuilder: (context, index) {

final item = snapshot.data.documents[index];
                          final itemID =
                              snapshot.data.documents[index].documentID;
                          final list = snapshot.data.documents;      
return Dismissible(
   key: Key(itemID),
              // We also need to provide a function that tells our app
              // what to do after an item has been swiped away.
              onDismissed: (direction) {
                // Remove the item from our data source.

                //fBtDoc.deleteTraveldoc(item);
                //Firestore.instance.collection('/users/User1/Trips/${widget.tripId}/TropDocs/').document('$itemID').delete();
                setState(() {
                  list.removeAt(index);
                });

                // Then show a snackbar!
                Scaffold.of(context)
                    .showSnackBar(SnackBar(content: Text("$item dismissed")));
              },
              // Show a red background as the item is swiped away
              background: Container(color: Colors.red),
              child: _buildlistitem(
                            context, snapshot.data.documents[index])
);

                        }
                      );
                    },
                  ),
                )

Probably, I'm late, but I think it will be helpful for others.可能,我迟到了,但我认为这对其他人会有所帮助。 Had the same problem and even setting有同样的问题,甚至设置

key: Key(itemId[index]),

didn't work.没用。 However,然而,

key: UniqueKey(),

worked perfectly for me非常适合我

I think that's because you are trying to use same key for every dismissible.我认为那是因为您试图对每个可解雇的人使用相同的key

key: Key(itemID)

It should be key: Key(itemID[index])它应该是key: Key(itemID[index])

In my cause, I have used as below在我的事业中,我使用如下

key: Key(index),

and then I did change it as below.然后我确实将其更改如下。 It's working它正在工作

key: UniqueKey(),

Remove setState block, streamBuilder will rebuild list by itself移除 setState 块,streamBuilder 将自行重建列表

 setState(() {
   list.removeAt(index);
 });

The reason is that the value passed to the key property isn't unique or related to the index of a list.原因是传递给 key 属性的值不是唯一的或与列表的索引相关。 The solution is quite simple and all you need to do is set the key property to UniqueKey(), like this:解决方案非常简单,您只需将 key 属性设置为 UniqueKey(),如下所示:

key: UniqueKey(),

I would have done something like this to remove swiping from right to left我会做这样的事情来消除从右到左的滑动

                        confirmDismiss: (direction) {
                      return Future.value(direction == DismissDirection.endToStart);
                    },
                    onDismissed: (direction) {
                      setState(() {
                        list.removeAt(index);
                      });
                    },

A workaround for a single widget dismissible is shown below and for the dismissible in a list write logic according to the code provided.下面显示了单个小部件可关闭的解决方法,以及根据提供的代码在列表写入逻辑中可关闭的解决方法。 Here we put an if condition for the Dismissible and in onDismissed just set that bool variable to false so that it will not remains in the widget tree.在这里,我们为 Dismissible 设置了一个 if 条件,在onDismissed中,只需将该 bool 变量设置为 false,这样它就不会保留在小部件树中。

if (_boolVariable)
 Dismissible(
    key: Key('anyString'),
    onDismissed: (direction) {
      //your code here
      setState(() => _boolVariable = false);
    },
  child: YourWidget())

将密钥更改为:

key: UniqueKey(),

try to change remove(index) function under onDismissed: like that;尝试更改 onDismissed 下的 remove(index) 函数:就像那样;

 ***- mylist.removeAt(index);***

Because, remove function removes items.因为,删除功能会删除项目。 And yo dismissed nothing but looks dismissed and trows error : A dismissed Dismissible widget is still part of the tree.并且你什么都没解雇,只是看起来被解雇并引发错误:被解雇的 Dismissible 小部件仍然是树的一部分。

***- so must be declared like this : mylist.remove(item);***

My problem我的问题

I have had a similar problem, but a little bit more complex.我遇到过类似的问题,但有点复杂。 I wanted to use ReordableListView with ListTile 's along with Dismissible .我想将ReordableListViewListTile的以及Dismissible一起使用。

My code我的代码

Container(
  child: ReorderableListView.builder(
    onReorder: (int oldIndex, int newIndex) {},
    itemCount: _savedLocations.length,
    itemBuilder: (context, index) {
      LocationModel? locationItem = _savedLocations?[index];
        return Dismissible(
        // key: UniqueKey(),
        // key: Key('$index'),
        key: Key('${locationItem?.id}'),
        onDismissed: (direction) {
          LocationModel dismissed = _savedLocations[index];
          setState(() { _savedLocations.removeAt(index); });
          ScaffoldMessenger.of(context).showSnackBar(SnackBar(
          content: Text('Location: $dismissedValue dismissed')));
        },
        child: ListTile(
          // key: Key('$index'),
          // key: UniqueKey(),
          key: ValueKey('${locationItem?.id}'),
          title: Text(locationItem?.name ?? ''),
          subtitle: Text(locationItem?.country ?? ''),
        ),
    ),
),

Detailed explanation详细解释

I have started with ListTile and added key: Key('$index') , everything was working as expected.我从ListTile开始并添加了key: Key('$index') ,一切都按预期工作。 Then I wanted to add dismiss functionality so I wrapped it in Dismissible .然后我想添加关闭功能,所以我将它包装在Dismissible中。 Dismissible item also expect unique key, but I found out that actions on items with key: UniqueKey() assigned stopped working (dragging, dismissible). Dismissible item 也需要唯一键,但我发现对带有key: UniqueKey() assigned 的项目的操作停止工作(拖动,dismissible)。

Note: I have left commented out lines with wrong keys.注意:我已经用错误的键注释掉了行。 For example: Key('$index') cannot be used for Dismissible because it will be deleted at the time of dismissal and causes error.例如: Key('$index')不能用于Dismissible ,因为在dismissible的时候会被删除导致错误。 I strongly suggest you to try it and see the error when trying to dismiss list item by swiping left or right.我强烈建议您尝试通过向左或向右滑动来关闭列表项时看到错误。

Solution解决方案

Solution was to set Dismissible key to unique item Key('${locationItem?.id}') and ListTile key to ValueKey('${locationItem?.id}') .解决方案是将Dismissible键设置为唯一项Key('${locationItem?.id}')并将ListTile键设置为ValueKey('${locationItem?.id}') In this is case both Drag&drop (reordable) and dismissible funcionality work as expected.在这种情况下,拖放(可重新记录)和可关闭功能都按预期工作。

Hope it helps希望能帮助到你

Reference: How to use ReorderableListView with DismissDirection in Flutter?参考: How to use ReorderableListView with DismissDirection in Flutter?

Why giving index as key not working为什么给索引作为键不起作用

key: Key(index) : in this case the widget in widget tree will be bind in to the key which is the index, when you remove an item from the tree the build method will re-run and it looks for the widget with the key is there and always it can find the index there as the next element in the list will be replaced by the current item with "same index" that is why you are not getting this error when you try to remove it from end of the list the index can't be replaced because there is no element after this so instead of using index as key use something unique in that element like the id of element or UniqueKey() key: Key(index) :在这种情况下,小部件树中的小部件将绑定到作为索引的键,当您从树中删除一个项目时,构建方法将重新运行并查找带有key 在那里并且它总是可以在那里找到索引,因为列表中的下一个元素将被具有“相同索引”的当前项目替换,这就是为什么当您尝试从列表末尾删除它时没有收到此错误的原因无法替换索引,因为在此之后没有元素,所以不要使用索引作为键,而是使用该元素中唯一的东西,例如元素的 id 或UniqueKey()

key: Key(index) will throw error key: Key(index)会抛出错误

use采用

key: Key(item.id), or key: UniqueKey(), key: Key(item.id),key: UniqueKey(),

I'am also fall this error & debug with the following logic Instead of我也遇到了这个错误并使用以下逻辑进行调试而不是

key: Key(itemID),

use利用

key: Key(itemID[itemIDIndex]),

and in your setstae logic replace在你的 setstae 逻辑中替换

setState(() {
              list.removeAt(index);
            });

with

setState(() {
              itemID.removeAt(itemIDIndex);
            });

this will solve the problem.这将解决问题。

For reference see the Image Screenshot参考图片截图项目生成器 在此处删除索引

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何修复“已关闭的 Dismissible 小部件仍然是树的一部分。” 在 flutter - How to fix 'A dismissed Dismissible widget is still part of the tree.' in flutter 已关闭的 Dismissible 小部件仍然是树的一部分。 在 flutter - A dismissed Dismissible widget is still part of the tree. In flutter Flutter:已关闭的可关闭小部件仍然是树的一部分 - Flutter: a dismissed dismissible widget is still part of the tree 已关闭的 Dismissible 小部件仍然是 flutter 中树的一部分 - A dismissed Dismissible widget is still part of the tree in flutter 已关闭的 Dismissible 小部件仍然是树的一部分。 从列表中删除项目后重复出现此错误 - A dismissed Dismissible widget is still part of the tree. Getting this error repeatedly after removing item from list 被关闭的 Dismissible 小部件仍然是树的一部分 - A dismissed Dismissible widget is still part of the tree Flutter Dismissed Dismissible 小部件仍然是树问题的一部分,无法解决 - Flutter Dismissed Dismissible widget still part of tree issue, can't resolve `一个被解雇的 Dismissible 小部件仍然是树的一部分`错误突然发生(FutureBuilder,ListView) - `A dismissed Dismissible widget is still part of the tree` error occurred suddenly (FutureBuilder, ListView) 如何解决问题:使用 Bloc 时“已关闭的 Dismissible 小部件仍然是树的一部分” - How to resolve issue: “A dismissed Dismissible widget is still part of the tree” while use Bloc 在 Flutter 中,是否可以增加 Dismissible 小部件的透明度? - In Flutter is it possible to increase the transparency of a Dismissible widget the further it is dismissed?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM