如何正确排序对象列表并克隆它

时间:2020-10-08 20:15:58

标签: list flutter dart

因此,我正在使用StaggeredGridView创建此应用程序,该应用程序是在线商店的商品目录,在这里我添加了一个功能,用于从列表中对商品进行排序,以便我可以按价格对商品进行排序或将其恢复为默认排序,但是我遇到一个问题,当我选择列表时,列表无法返回默认排序,这是代码:

class ItemCatalogState extends State<ItemCatalog>{

  sortedBy sorted = sortedBy.init;
  bool isInit = true;
  var selectedList = [];

  void sortItem(List<Item> initialList){
    switch (sorted) {
      case sortedBy.lowestPrice:
        setState(() {
          selectedList.sort((a,b){return a.price.compareTo(b.price);}); 
        });
        break;
      case sortedBy.highestPrice:
        setState(() {
          selectedList.sort((a,b){return b.price.compareTo(a.price);});
        });
        break;
      case sortedBy.init:
      //NOT WORKING
        setState(() {
          selectedList = initialList; 
        });
        break;
       default:
    }
  }

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    List<Item> itemList = Provider.of<List<Item>>(context);
    
    if(isInit&&itemList!=null){
      selectedList = itemList.map((e) => Item(image: e.image,name: e.name,isReady: e.isReady,price: e.price,seller: e.seller)).toList();
      isInit = false;
    }

    sortItem(itemList);

    return Container(
          child: DropdownButtonHideUnderline(
            child: DropdownButton(
              value: sorted,
              items: [
                DropdownMenuItem(
                  child: Text('Default',),
                  value: sortedBy.init,),
                DropdownMenuItem(
                  child: Text('Lowest',),
                  value: sortedBy.lowestPrice,),
                DropdownMenuItem(
                  child: Text('Highest'),
                  value: sortedBy.highestPrice,),
              ], 
              onChanged: (value){
                setState(() {
                  sorted = value;
                });
              }),
          ),
        ),
        Container(
                  decoration: BoxDecoration(
                    color: kGrayMainColor,
                  ),
                  child: StaggeredGridView.countBuilder(
                    itemCount: selectedList!=null?selectedList.length:itemList.length,
                    crossAxisCount: 2,
                    itemBuilder: (context, index) {
                      Item currentItem = selectedList!=null?selectedList[index]:itemList[index];
                      return ItemTile(item: currentItem, size: size,);
                    },
                  ),
                ),
              ),
      ]),]
    );
  }

当我单击默认下拉列表时,应该调用原始列表,但是没有任何更改,将列表复制到selectedList可能会出错吗?谢谢,关于我的其他不良代码实践的任何建议也值得赞赏,因为我仍在学习。

2 个答案:

答案 0 :(得分:1)

sortItems内,您将selectedList设置为等于initialList。从那时起,两个变量现在都指向同一对象集合,这意味着您对一个对象执行的任何操作,对另一个对象也将执行的操作。并且由于您是通过提供程序获取集合的,所以这些更改还将影响所提供的原始列表。

代替直接分配,请再次复制initialList,以使两个列表永远不会指向同一集合。

顺便说一句,有一种更简单的方法来创建列表副本:

selectedList = List.from(initialList);

另一方面,我假设sorted的默认值为sortedBy.init。这会使build方法中的初始副本变得多余,因为sortItems方法会立即覆盖selectedList的值。相反,只需依靠sortItems来生成列表,而不必担心初始化:

void sortItem(List<Item> initialList){
  switch (sorted) {
    case sortedBy.lowestPrice:
      selectedList = List.from(initialList)
        ..sort((a,b) => a.price.compareTo(b.price));
      break;
    case sortedBy.highestPrice:
      selectedList = List.from(initialList)
        ..sort((a,b) => b.price.compareTo(a.price));
      break;
    case sortedBy.init:
      selectedList = List.from(initialList); 
      break;
  }
  setState(() {}); // Just call this once to reduce code duplication and verbosity
}

@override
Widget build(BuildContext context) {
  ...

  List<Item> itemList = Provider.of<List<Item>>(context);
  sortItems(itemList);

  ...
}

答案 1 :(得分:0)

这就是我要解决的方法(为简单起见,我将您的List<Item>更改为List<String>,但您的要旨是)

通过Provider将原始列表加载到_sortedList变量中(最初在didChangeDependencies中),并在需要再次使用原始列表时重复此操作。

(我的提供者返回了['aa', 'dd', 'cc'],所以我也可以进入列表中的map():))

enum SortOrder { ascending, descending, original }

class _TestState extends State<Test> {
  var _sortedList = List<String>();

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _loadOriginalList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              RaisedButton(
                child: Text('Ascending'),
                onPressed: () => setState(() => _sortList(SortOrder.ascending)),
              ),
              RaisedButton(
                child: Text('Descending'),
                onPressed: () => setState(() => _sortList(SortOrder.descending)),
              ),
              RaisedButton(
                child: Text('Original'),
                onPressed: () => setState(() => _sortList(SortOrder.original)),
              ),
            ],
          ),
          ListView.builder(
            shrinkWrap: true,
            itemCount: _sortedList.length,
            itemBuilder: (context, index) => Center(
              child: Text(_sortedList[index]),
            ),
          ),
        ],
      ),
    );
  }

  void _sortList(SortOrder sortOrder) {
    switch (sortOrder) {
      case SortOrder.ascending:
        _sortedList.sort();
        break;
      case SortOrder.descending:
        _sortedList.sort();
        _sortedList = _sortedList.reversed.toList();
        break;
      case SortOrder.original:
        _loadOriginalList();
        break;
    }
  }

  void _loadOriginalList() {
    final originalList = Provider.of<List<String>>(context, listen: false);
    _sortedList.clear();
    _sortedList.addAll(originalList.map((e) => e.substring(0, 1)));
  }
}
相关问题