为何Flutter中修改_filter_data会同步更新masterData?
问题
我编写的Flutter代码运行符合预期,但我不理解其原理。我定义了两个List:
List<ProductInfo>_filter_data = []; List<ProductInfo>masterData = [];
应用启动时从数据表构建masterData,在应用内根据用户操作过滤数据:
List<ProductInfo> results = []; results = masterData.where((user) => type == user.selectedType ).toList(); //简化示例 setState(() { _filter_data = results; });
通过ListView基于_filter_data展示数据,用户可通过复选框标记收藏:
setState(() { if (isChecked) { _filter_data[widget.data_index].fav = true; } else { _filter_data[widget.data_index].fav = false; }
按我的理解,修改_filter_data的fav属性不应影响masterData,重新过滤后收藏选择会丢失,但实际两者的fav属性都被更新了。我通过调试打印确认了这一点,想知道原因,是否是ProductInfo对象在两个列表中共享?这正是我想要的行为,但我不明白代码为何会这样运行。
解答
你猜的完全正确——两个列表里的ProductInfo对象确实是共享的,核心原因在于Dart的对象引用机制:
- Dart中,自定义类(比如
ProductInfo)的实例属于引用类型,变量存储的不是对象本身,而是指向内存中该对象的引用地址。 - 当你通过
masterData.where(...).toList()生成过滤后的列表时,这个新列表并没有创建ProductInfo对象的副本,只是把原masterData中符合条件的对象引用直接拿过来放进了新列表。也就是说,_filter_data和masterData里的对应元素,指向的是内存中同一个ProductInfo实例。 - 所以你修改
_filter_data[widget.data_index].fav时,本质是在修改内存中那个共享对象的属性,masterData里对应的对象自然也会同步变化——因为它们本来就是同一个东西。
这种行为刚好契合你的需求,能让你在过滤后的列表里修改收藏状态,同时同步保留到原始数据中,重新过滤后也不会丢失用户的选择。
如果之后你需要创建完全独立、不共享对象的列表,就需要为每个对象创建副本,比如在过滤时使用map方法复制属性:
results = masterData.where((user) => type == user.selectedType) .map((product) => ProductInfo( id: product.id, selectedType: product.selectedType, fav: product.fav, // 复制其他需要的属性 )) .toList();
这样新列表里的就是全新的ProductInfo实例,修改它们的属性就不会影响masterData了。
内容的提问来源于stack exchange,提问作者R. Denver
相关产品推荐
相关产品推荐

