簡體   English   中英

如何修復“已關閉的 Dismissible 小部件仍然是樹的一部分。” flutter 錯誤

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

我正在構建一個帶有 dismissible 小部件 firebase 和 StreamBuilder 的 flutter 應用程序,並收到以下錯誤“A dismissed Dismissible widget is still part of the tree.”

請找到以下相同的代碼。

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])
);

                        }
                      );
                    },
                  ),
                )

可能,我遲到了,但我認為這對其他人會有所幫助。 有同樣的問題,甚至設置

key: Key(itemId[index]),

沒用。 然而,

key: UniqueKey(),

非常適合我

我認為那是因為您試圖對每個可解雇的人使用相同的key

key: Key(itemID)

它應該是key: Key(itemID[index])

在我的事業中,我使用如下

key: Key(index),

然后我確實將其更改如下。 它正在工作

key: UniqueKey(),

移除 setState 塊,streamBuilder 將自行重建列表

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

原因是傳遞給 key 屬性的值不是唯一的或與列表的索引相關。 解決方案非常簡單,您只需將 key 屬性設置為 UniqueKey(),如下所示:

key: UniqueKey(),

我會做這樣的事情來消除從右到左的滑動

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

下面顯示了單個小部件可關閉的解決方法,以及根據提供的代碼在列表寫入邏輯中可關閉的解決方法。 在這里,我們為 Dismissible 設置了一個 if 條件,在onDismissed中,只需將該 bool 變量設置為 false,這樣它就不會保留在小部件樹中。

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

將密鑰更改為:

key: UniqueKey(),

嘗試更改 onDismissed 下的 remove(index) 函數:就像那樣;

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

因為,刪除功能會刪除項目。 並且你什么都沒解雇,只是看起來被解雇並引發錯誤:被解雇的 Dismissible 小部件仍然是樹的一部分。

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

我的問題

我遇到過類似的問題,但有點復雜。 我想將ReordableListViewListTile的以及Dismissible一起使用。

我的代碼

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 ?? ''),
        ),
    ),
),

詳細解釋

我從ListTile開始並添加了key: Key('$index') ,一切都按預期工作。 然后我想添加關閉功能,所以我將它包裝在Dismissible中。 Dismissible item 也需要唯一鍵,但我發現對帶有key: UniqueKey() assigned 的項目的操作停止工作(拖動,dismissible)。

注意:我已經用錯誤的鍵注釋掉了行。 例如: Key('$index')不能用於Dismissible ,因為在dismissible的時候會被刪除導致錯誤。 我強烈建議您嘗試通過向左或向右滑動來關閉列表項時看到錯誤。

解決方案

解決方案是將Dismissible鍵設置為唯一項Key('${locationItem?.id}')並將ListTile鍵設置為ValueKey('${locationItem?.id}') 在這種情況下,拖放(可重新記錄)和可關閉功能都按預期工作。

希望能幫助到你

參考: How to use ReorderableListView with DismissDirection in Flutter?

為什么給索引作為鍵不起作用

key: Key(index) :在這種情況下,小部件樹中的小部件將綁定到作為索引的鍵,當您從樹中刪除一個項目時,構建方法將重新運行並查找帶有key 在那里並且它總是可以在那里找到索引,因為列表中的下一個元素將被具有“相同索引”的當前項目替換,這就是為什么當您嘗試從列表末尾刪除它時沒有收到此錯誤的原因無法替換索引,因為在此之后沒有元素,所以不要使用索引作為鍵,而是使用該元素中唯一的東西,例如元素的 id 或UniqueKey()

key: Key(index)會拋出錯誤

采用

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

我也遇到了這個錯誤並使用以下邏輯進行調試而不是

key: Key(itemID),

利用

key: Key(itemID[itemIDIndex]),

在你的 setstae 邏輯中替換

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

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

這將解決問題。

參考圖片截圖項目生成器 在此處刪除索引

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM