如何在Dart/Flutter中正确过滤列表且不丢失原数据?
解决Dart/Flutter过滤列表时丢失原始数据的问题
问题根源
你当前的核心问题是直接将过滤结果赋值回了原始列表widget.collection!.items,导致原始的100条数据被覆盖,无法恢复。另外你的filterCollection方法逻辑冗余,没有起到保留原始数据的作用。
解决方案:分离原始数据源与展示用列表
核心思路是:始终保留原始列表不动,单独维护一个用于ListView展示的过滤后列表,所有过滤操作只修改展示列表,不碰原始数据。
1. 在页面状态类中新增展示列表变量
在你的State类里添加一个专门用于展示的列表,初始化时复制原始列表的内容(切断引用关联):
List<Item> _displayItems = []; @override void initState() { super.initState(); // 用List.from创建原始列表的副本,避免和原始列表共享引用 _displayItems = List.from(widget.collection!.items); }
2. 修改过滤触发逻辑,只更新展示列表
点击按钮时,不再修改原始的widget.collection!.items,而是更新_displayItems并触发UI刷新:
onTap: (int index) { setState(() { switch (index) { case 0: // 恢复展示全部数据:重新复制原始列表 _displayItems = List.from(widget.collection!.items); _selectedIndex = index; break; case 1: // 直接基于原始列表过滤,生成新的展示列表 _displayItems = widget.collection!.items .where((element) => element.something == true) .toList(); _selectedIndex = index; break; } }); }
3. 优化filterCollection方法(可选)
如果想保留封装的过滤方法,修改它让它基于原始列表返回过滤结果,绝对不修改原始items:
List<Item> filterCollection(FilterType filter) { switch (filter) { case FilterType.onlyFew: // 基于原始列表过滤,返回新列表 return items.where((element) => element.something == true).toList(); case FilterType.all: default: // 返回原始列表的副本,避免外部修改影响原始数据 return List.from(items); } }
调用时改为:
_displayItems = widget.collection!.filterCollection(FilterType.onlyFew);
关于列表引用的说明
- Dart中
List.from()/List.of()会创建浅拷贝的新列表:如果你的Item是不可变类(所有字段都是final),完全够用;如果Item是可变类,只是列表本身的引用被复制,对象实例还是同一个,但这不会影响过滤操作(过滤是筛选元素,不是修改元素内容)。 - 若需要完全独立的深拷贝,可给
Item类实现copyWith方法,遍历原始列表逐个复制对象。
内容的提问来源于stack exchange,提问作者Icaroto
相关产品推荐
相关产品推荐

