在Flutter中List of ListTiles中有重复条目。

huangapple go评论48阅读模式
英文:

Duplicate entry in List of ListTiles - Flutter

问题

I am trying to add items to a 'cart' list from my interface and see that for specific items, adding a different item produces a duplicate entry.

List<Widget> _subSubExpansionTiles(BuildContext context, List<Item> itemSubList) {
    // this makes the second level of ExpansionTiles - the item, i.e. "Regular", "Starch" etc
    List<Widget> _subSubList = [];

    var groupedActionLists = groupBy(itemSubList, (Item item) => item.service);
    //print(groupedActionLists.keys.toList());
    Map<String, Map<String, dynamic>> counter = {};

    print("*************************${groupedActionLists.keys} ****************************************");
    for(var key in groupedActionLists.keys) {   // Wash And Fold, Wash And Iron
        //print("$key : ${groupedActionLists[key]!.length.toString()}");
        print("*************$key : ${groupedActionLists[key]!.length} ******************");
        Map<String, dynamic> subMap = {};
        int regular = 0;
        int regularStarch = 0;
        int stainRemoval = 0;
        int stainRemovalStarch = 0;
        for(Item item in groupedActionLists[key]!) {
            if (item.starch == null && item.stainRemoval == null) {
                regular++;
            }
            else if (item.starch != null && item.stainRemoval == null) {
                if (item.starch == false) {
                    regular++;
                } else {
                    regularStarch++;
                }
            }
            else if (item.starch == null && item.stainRemoval != null) {
                if (item.stainRemoval == false) {
                    regular++;
                } else {
                    stainRemoval++;
                }
            }
            else if (item.starch != null && item.stainRemoval != null) {
                if (item.starch == false && item.stainRemoval == false) {
                    regular++;
                } else if (item.starch == true && item.stainRemoval == false) {
                    regularStarch++;
                } else if (item.starch == false && item.stainRemoval == true) {
                    stainRemoval++;
                } else if (item.starch == true && item.stainRemoval == true) {
                    stainRemovalStarch++;
                }
            }

            subMap.addEntries({'regular' : regular}.entries);
            subMap.addEntries({'regularStarch' : regularStarch}.entries);
            subMap.addEntries({'stainRemoval' : stainRemoval}.entries);
            subMap.addEntries({'stainRemovalStarch' : stainRemovalStarch}.entries);

            counter.addEntries({item.service! : subMap}.entries);
        };
        //print(counter);
        String prevKey = "";
        for(var key in counter.keys){
            print("Iterating through $key");
            for (var subkey in counter[key]!.keys) {
                //print("${counter[key]!.keys}");
                String nameString = '';
                if (subkey == 'regular')
                    nameString = key;
                else if (subkey == 'regularStarch')
                    nameString = key + '+ Starch';
                else if (subkey == 'stainRemoval')
                    nameString = key + '+ Stain Removal';
                else if (subkey == 'stainRemovalStarch') nameString = key + '+ Stain Removal + Starch';
                if (counter[key]![subkey] > 0) {
                    print("adding : $nameString");
                    _subSubList.add(ListTile(
                        title: Text(nameString),
                        visualDensity: VisualDensity.compact,
                        leading: Padding(padding: EdgeInsets.fromLTRB(5, 0, 5, 0)),
                        trailing: Text(
                            counter[key]![subkey].toString(),
                            style: const TextStyle(
                                fontSize: 15,
                            ),
                        )));
                }
                //print("$key : ${counter[key]![subkey]}");
            }
        }
    }
    //print("returning $_subSubList");
    return (_subSubList);
}

I get the following output, where as we can see 'Wash and Iron' is repeated twice. The converse is also true - when I add Wash and Fold first and then Wash and Iron, I see Wash and Fold twice.

Here the Item class has the following members:

class Item implements Jsonifyable {
    String? id;
    String? item;
    String? image;

    String? action;

    String? service;
    bool? starch;
    bool? stainRemoval;

    Item({
        this.id,
        this.item,
        this.image,
        this.action,
        String? service,
        this.starch,
        this.stainRemoval,
    })

[![Screenshot][1]][1]

I've added debug statements to understand what is going on and I get:

Reloaded 8 of 1506 libraries in 1,799ms (compile: 202 ms, reload: 546 ms, reassemble: 1026 ms).
I/flutter (10344): *************************(Wash and Iron, Wash and Fold) ****************************************
I/flutter (10344): *************Wash and Iron : 1 ******************
I/flutter (10344): Iterating through Wash and Iron
I/flutter (10344): adding : Wash and Iron
I/flutter (10344): *************Wash and Fold : 1 ******************
I/flutter (10344): Iterating through Wash and Iron
I/flutter (10344): adding : Wash and Iron
I/flutter (10344): Iterating through Wash and Fold
I/flutter (10344): adding : Wash and Fold

Here the _subsublist function is invoked by the following functions:

List<Widget> _subExpansionTiles(BuildContext context, List<Item> itemList) {
    // this makes the first level of ExpansionTiles - the item, i.e. "Shirt", "Trouser" etc
    String action = itemList[0].action!;
    List<Widget> itemTiles = [];
    var groupedIdLists = groupBy(itemList, (Item item) => item.id);
    // we get {'S001' : [], 'S002' : [] ... etc ... } 
    groupedIdLists.forEach((key, value) {
        List<Item> _subItemList = value;
        String itemName = _subItemList[0].item!;
        var tile = ExpansionTile(
            title: Text(itemName),
            subtitle: Text('Click to expand'),
            controlAffinity: ListTileControlAffinity.leading,
            maintainState: true,
            trailing: Text(
                _subItemList.length.toString(),
                style: const TextStyle(
                    fontSize: 20,
                ),
            ),
            children: _subSubExpansionTiles(context, _subItemList));
        itemTiles.add(tile);
    });
    return itemTiles;
}

Widget _buildExpansionTiles(BuildContext context, String category) {
    // this makes the first level of ExpansionTiles - the item, i.e. "Iron", "Dry Clean", etc
    if (!cartItems.containsKey(category)) {
        return SliverToBoxAdapter(child: Container());
    }
    List<Item> _categoryItems = cartItems[category]

<details>
<summary>英文:</summary>

I am trying to add items to a &#39;cart&#39; list from my interface and see that for specific items, adding a different item produces a duplicate entry.



     List&lt;Widget&gt; _subSubExpansionTiles(BuildContext context, List&lt;Item&gt; itemSubList) {
    // this makes the second level of ExpansionTiles - the item , i.e. &quot;Regular&quot;, &quot;Starch&quot; etc
    List&lt;Widget&gt; _subSubList = [];

    var groupedActionLists = groupBy(itemSubList, (Item item) =&gt; item.service);
    //print(groupedActionLists.keys.toList());
    Map&lt;String, Map&lt;String, dynamic&gt;&gt; counter = {};

    print(&quot;*************************${groupedActionLists.keys} ****************************************&quot;);
    for(var key in groupedActionLists.keys) {   // Wash And Fold, Wash And Iron
      //print(&quot;$key : ${groupedActionLists[key]!.length.toString()}&quot;);
      print(&quot;*************$key : ${groupedActionLists[key]!.length} ******************&quot;);
      Map&lt;String, dynamic&gt; subMap = {};
      int regular = 0;
      int regularStarch = 0;
      int stainRemoval = 0;
      int stainRemovalStarch = 0;
      for(Item item in groupedActionLists[key]!) {
        if (item.starch == null &amp;&amp; item.stainRemoval == null) {
          regular++;
        }
        else if (item.starch != null &amp;&amp; item.stainRemoval == null) {
          if (item.starch == false) {
            regular++;
          } else {
            regularStarch++;
          }
        }
        else if (item.starch == null &amp;&amp; item.stainRemoval != null) {
          if (item.stainRemoval == false) {
            regular++;
          } else {
            stainRemoval++;
          }
        }
        else if (item.starch != null &amp;&amp; item.stainRemoval != null) {
          if (item.starch == false &amp;&amp; item.stainRemoval == false) {
            regular++;
          } else if (item.starch == true &amp;&amp; item.stainRemoval == false) {
            regularStarch++;
          } else if (item.starch == false &amp;&amp; item.stainRemoval == true) {
            stainRemoval++;
          } else if (item.starch == true &amp;&amp; item.stainRemoval == true) {
            stainRemovalStarch++;
          }
        }

        subMap.addEntries({&#39;regular&#39; : regular}.entries);
        subMap.addEntries({&#39;regularStarch&#39; : regularStarch}.entries);
        subMap.addEntries({&#39;stainRemoval&#39; : stainRemoval}.entries);
        subMap.addEntries({&#39;stainRemovalStarch&#39; : stainRemovalStarch}.entries);

        counter.addEntries({item.service! : subMap}.entries);
      };
      //print(counter);
      String prevKey = &quot;&quot;;
      for(var key in counter.keys){
        print(&quot;Iterating through $key&quot;);
        for (var subkey in counter[key]!.keys) {
          //print(&quot;${counter[key]!.keys}&quot;);
          String nameString = &#39;&#39;;
          if (subkey == &#39;regular&#39;)
            nameString = key;
          else if (subkey == &#39;regularStarch&#39;)
            nameString = key + &#39;+ Starch&#39;;
          else if (subkey == &#39;stainRemoval&#39;)
            nameString = key + &#39;+ Stain Removal&#39;;
          else if (subkey == &#39;stainRemovalStarch&#39;) nameString = key + &#39;+ Stain Removal + Starch&#39;;
          if (counter[key]![subkey] &gt; 0) {
            print(&quot;adding : $nameString&quot;);
            _subSubList.add(ListTile(
                title: Text(nameString),
                visualDensity: VisualDensity.compact,
                leading: Padding(padding: EdgeInsets.fromLTRB(5, 0, 5, 0)),
                trailing: Text(
                  counter[key]![subkey].toString(),
                  style: const TextStyle(
                    fontSize: 15,
                  ),
                )));
          }
          //print(&quot;$key : ${counter[key]![subkey]}&quot;);
        }
      }
    }
    //print(&quot;returning $_subSubList&quot;);
    return (_subSubList);
  }

I get the following output, where as we can see &#39;Wash and Iron&#39; is repeated twice. The converse is also true - when I add Wash and Fold first and then Wash and Iron, I see Wash and Fold twice.

Here the Item class has the following members:

        
    class Item implements Jsonifyable {
      String? id;
      String? item;
      String? image;
    
      String? action;
    
      String? service;
      bool? starch;
      bool? stainRemoval;
    
      Item({
        this.id,
        this.item,
        this.image,
        this.action,
        String? service,
        this.starch,
        this.stainRemoval,
      })

[![Screenshot][1]][1]

I&#39;ve added debug statements to understand what is going on and I get:

    Reloaded 8 of 1506 libraries in 1,799ms (compile: 202 ms, reload: 546 ms, reassemble: 1026 ms).
    I/flutter (10344): *************************(Wash and Iron, Wash and Fold) ****************************************
    I/flutter (10344): *************Wash and Iron : 1 ******************
    I/flutter (10344): Iterating through Wash and Iron
    I/flutter (10344): adding : Wash and Iron
    I/flutter (10344): *************Wash and Fold : 1 ******************
    I/flutter (10344): Iterating through Wash and Iron
    I/flutter (10344): adding : Wash and Iron
    I/flutter (10344): Iterating through Wash and Fold
    I/flutter (10344): adding : Wash and Fold

Here the _subsublist function is invoked by the following functions:


      List&lt;Widget&gt; _subExpansionTiles(BuildContext context, List&lt;Item&gt; itemList) {
        // this makes the first level of ExpansionTiles - the item , i.e. &quot;Shirt&quot;, &quot;Trouser&quot; etc
        String action = itemList[0].action!;
        List&lt;Widget&gt; itemTiles = [];
        var groupedIdLists = groupBy(itemList, (Item item) =&gt; item.id);
        // we get {&#39;S001&#39; : [], &#39;S002&#39; : [] ... etc ... } 
        groupedIdLists.forEach((key, value) {
          List&lt;Item&gt; _subItemList = value;
          String itemName = _subItemList[0].item!;
          var tile = ExpansionTile(
              title: Text(itemName),
              subtitle: Text(&#39;Click to expand&#39;),
              controlAffinity: ListTileControlAffinity.leading,
              maintainState: true,
              trailing: Text(
                _subItemList.length.toString(),
                style: const TextStyle(
                  fontSize: 20,
                ),
              ),
              children: _subSubExpansionTiles(context, _subItemList));
          itemTiles.add(tile);
        });
        return itemTiles;
      }
    
      Widget _buildExpansionTiles(BuildContext context, String category) {
        // this makes the first level of ExpansionTiles - the item , i.e. &quot;Iron&quot;, &quot;Dry Clean&quot;, etc
        if (!cartItems.containsKey(category)) {
          return SliverToBoxAdapter(child: Container());
        }
        List&lt;Item&gt; _categoryItems = cartItems[category]!;
        if (_categoryItems.length == 0) return SliverToBoxAdapter(child: Container());
        String action = _categoryItems[0].action!;
        return SliverToBoxAdapter(
          child: ExpansionTile(
            title: Text(action),
            subtitle: Text(&#39;Click to expand&#39;),
            controlAffinity: ListTileControlAffinity.trailing,
            maintainState: true,
            leading: Text(
              _categoryItems.length.toString(),
              style: const TextStyle(
                fontSize: 25,
              ),
            ),
            children: _subExpansionTiles(context, _categoryItems),
          ),
        );
      }


Can anyone help me figure out why there is a duplicate entry?

  [1]: https://i.stack.imgur.com/D5zND.png


</details>


# 答案1
**得分**: 1

把以下这行代码:

Map<String, Map<String, dynamic>> counter = {};

移动到以下这行代码下面:

for (var key in groupedActionLists.keys) { // Wash And Fold, Wash And Iron

因为现在当它到达循环中的第二个键时,`counter` 仍然被前一个循环填充。将其移动到循环内部会从一个空的计数器开始。

<details>
<summary>英文:</summary>

I&#39;m not entirely sure but I believe you need to move the line

    Map&lt;String, Map&lt;String, dynamic&gt;&gt; counter = {};

to below the line

    for(var key in groupedActionLists.keys) {   // Wash And Fold, Wash And Iron

because now when it reaches the second key in the loop the `counter` is still filled by the previous loop. By moving it inside the loop it starts with a empty counter.

</details>



huangapple
  • 本文由 发表于 2023年6月26日 14:55:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76554188.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定