You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 00:01:19