如何在Dart/Flutter中正确复制列表/对象避免联动修改
问题原因
你遇到的是浅拷贝与深拷贝的差异问题。你之前尝试的所有列表复制方式都属于浅拷贝,仅创建了新的列表容器,列表内存储的仍然是原对象的内存引用——两个列表指向内存中同一批对象,修改任意一个列表内的对象属性,另一个列表的对应内容自然会同步变更。
你之前的操作具体差异如下:
list_2 = list_1:连新列表都未创建,只是给原列表多绑定了一个变量名,修改列表本身的增删操作也会同步List.of(list_1)、扩展运算符[...list_1]、toList()、循环add元素:仅生成了新的列表结构,内部存储的对象还是和原列表完全一致的引用,只会隔离列表本身的增删操作,不会隔离对象属性的修改
解决方法
你需要对列表内的每个自定义对象单独做深拷贝,也就是为每个对象生成全新的副本,再将副本存入新列表。
步骤1:给自定义类增加拷贝方法
假设你列表存储的是自定义的用户输入类,给类新增copyWith方法,用于生成新的同类对象:
class UserInput { String content; int type; // 假设还有其他自定义属性 UserInput({required this.content, required this.type}); // 拷贝方法,不传参数就返回完全相同的新对象,传参数可覆盖对应属性 UserInput copyWith({ String? content, int? type, }) { return UserInput( content: content ?? this.content, type: type ?? this.type, ); } }
如果你的类还嵌套了其他自定义类,嵌套的类也需要实现对应的copyWith方法,在父类的copyWith中同步调用嵌套类的拷贝方法即可。
步骤2:生成深拷贝的新列表
拷贝列表时,遍历每个元素调用copyWith生成新对象,再存入新列表:
// 写法1:用map遍历生成 List<UserInput> list_2 = list_1.map((item) => item.copyWith()).toList(); // 写法2:用for循环实现,和你之前的写法逻辑一致,仅新增拷贝对象的步骤 List<UserInput> list_2 = []; for (var item in list_1) { list_2.add(item.copyWith()); }
修改完成后再修改list_1内的对象属性,list_2的内容就不会再同步变更了。
补充说明
如果你的列表存储的是int、String、bool等基础数据类型,不需要做深拷贝,浅拷贝就可以满足需求,深拷贝仅针对自定义类对象的列表生效。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

