Flutter中如何对列表执行深拷贝,操作副本时不影响原列表数据
问题根因
List.from(_types) 属于浅拷贝,仅会创建一个新的列表容器,列表内存储的还是原_types中Type对象的引用,并没有生成新的Type实例。所以你修改_filteredTypes[i].subTypes属性时,本质是直接修改原列表中同一个Type对象的属性,自然会导致原始数据被篡改。
另外先修正你代码里的笔误:SubType类的构造函数名错写为Type了,需要修正为SubType,否则代码无法正常运行。
解决方案
你需要为Type、SubType类新增copyWith方法,过滤时生成全新的对象实例,完全不修改原对象的属性,实现逻辑如下:
第一步:给实体类补充copyWith方法
class SubType extends Equatable { final int id; final String title; SubType({ required this.id, required this.title, }); // 新增copyWith方法 SubType copyWith({ int? id, String? title, }) { return SubType( id: id ?? this.id, title: title ?? this.title, ); } @override List<Object?> get props => [id, title]; } class Type extends Equatable { final int id; final String title; List<SubType>? subTypes; Type({ required this.id, required this.title, this.subTypes, }); // 新增copyWith方法 Type copyWith({ int? id, String? title, List<SubType>? subTypes, }) { return Type( id: id ?? this.id, title: title ?? this.title, subTypes: subTypes ?? this.subTypes, ); } @override List<Object?> get props => [id, title, subTypes]; }
第二步:修改过滤逻辑,全程操作新生成的副本
_onSearchChangedEvent() { setState(() { final lowerQuery = query?.toLowerCase() ?? ''; // 直接遍历原列表,生成全新的筛选后列表,完全不修改原对象 _filteredTypes = _types.map((type) { // 筛选当前type下匹配的subType final matchedSubTypes = type.subTypes?.where((subType) => subType.title.toLowerCase().contains(lowerQuery) ).toList() ?? []; // 返回全新的Type实例,不会修改原type对象的任何属性 return type.copyWith(subTypes: matchedSubTypes); }) // 过滤掉没有匹配subType的type项 .where((newType) => newType.subTypes?.isNotEmpty == true) .toList(); bindTypes(); }); }
这种写法全程没有修改原_types列表里的任何对象属性,所有修改都在新生成的实例上操作,完全不会污染原始数据。
内容的提问来源于stack exchange,提问作者Osama Remlawi
相关产品推荐
相关产品推荐

