新列表在克隆后仍然引用旧列表
New list still references old list after being cloned
我有一个初始化如下的地图列表
List<dynamic> _people = [];
Map<String, dynamic> _person = {
'image' : null,
'name': null,
'age': null
};
在程序中的一个方法中,我打算将 _people
中的值复制到一个新的 List 变量中,以便我可以对其进行更改。
List _peopleCopy = List.from(_people);
for (var i=0; i < _people.length; i++) {
if (_people[i]['image'] != null) {
List<num> img = new List.from(_people[i]['image'].readAsBytesSync());
_peopleCopy[i]['image'] = img;
}
}
现在的问题是,每次我将 img
的值分配给 _peopleCopy
时,它也会更改 _people
列表中的相应值,即使我这样做了 List.from()
方法来克隆它。显然,我想保留 _people
列表的原始内容。我这里做错了什么?
您已成功创建新列表。但该列表包含对相同地图的引用。因此更改地图会在两个列表中更改它,因为它是相同的元素。
你也需要复制元素。
由于您的地图 还 包含您可能想要深度复制的 dynamic
类型,我建议只 jsonEncode
/jsonDecode
你的整个结构。序列化和反序列化不是最有效的方法,但它将创建其中任何结构的深层副本。
也就是说,Dart 是一种真正的编程语言。以这种方式使用它有很大帮助。如果您使用实际类型,而不是 dynamic
,它会变得更少猜测、祈祷和 duct-typing,而变得更加可靠、基于事实的编程。由于这似乎是 JSON 结构,因此使用 model classes。然后,您可以拥有自己的深度复制方法,并获得使用 dynamic
.
时无法获得的编译器支持
对于这种情况,我所做的是,我将对象的 originalJson 存储在对象 class 的变量中,如下所示,
class People {
int? age;
String? image;
String? name;
Map<String, dynamic> originalJson = {};
People({this.age, this.image, this.name});
People.fromJson(Map<String, dynamic> json) {
originalJson = json;
age = json['age']?.toInt();
image = json['image']?.toInt();
name = json['name']?.toString();
}
Map<String, dynamic> toJson() {
'age' = age;
'image' = image;
'name' = name;
}
}
因此,当您解析 http 响应时,现在您所要做的就是,
People.fromJson(json.decode(response.body));
这样您可以保留 json 并在克隆人员列表时,您所要做的就是,
// With the following line _people will now be new list with new objects but with mutated _people data
_people = _people.map((e) => People.fromJson(e.toJson())).toList();
// With the following line _people will now be new list with new objects but with data which we have recieved from the API call
_people = _people.map((e) => People.fromJson(e.originalJson)).toList();
这种维护 class 的方法肯定能帮到您..
我有一个初始化如下的地图列表
List<dynamic> _people = [];
Map<String, dynamic> _person = {
'image' : null,
'name': null,
'age': null
};
在程序中的一个方法中,我打算将 _people
中的值复制到一个新的 List 变量中,以便我可以对其进行更改。
List _peopleCopy = List.from(_people);
for (var i=0; i < _people.length; i++) {
if (_people[i]['image'] != null) {
List<num> img = new List.from(_people[i]['image'].readAsBytesSync());
_peopleCopy[i]['image'] = img;
}
}
现在的问题是,每次我将 img
的值分配给 _peopleCopy
时,它也会更改 _people
列表中的相应值,即使我这样做了 List.from()
方法来克隆它。显然,我想保留 _people
列表的原始内容。我这里做错了什么?
您已成功创建新列表。但该列表包含对相同地图的引用。因此更改地图会在两个列表中更改它,因为它是相同的元素。
你也需要复制元素。
由于您的地图 还 包含您可能想要深度复制的 dynamic
类型,我建议只 jsonEncode
/jsonDecode
你的整个结构。序列化和反序列化不是最有效的方法,但它将创建其中任何结构的深层副本。
也就是说,Dart 是一种真正的编程语言。以这种方式使用它有很大帮助。如果您使用实际类型,而不是 dynamic
,它会变得更少猜测、祈祷和 duct-typing,而变得更加可靠、基于事实的编程。由于这似乎是 JSON 结构,因此使用 model classes。然后,您可以拥有自己的深度复制方法,并获得使用 dynamic
.
对于这种情况,我所做的是,我将对象的 originalJson 存储在对象 class 的变量中,如下所示,
class People {
int? age;
String? image;
String? name;
Map<String, dynamic> originalJson = {};
People({this.age, this.image, this.name});
People.fromJson(Map<String, dynamic> json) {
originalJson = json;
age = json['age']?.toInt();
image = json['image']?.toInt();
name = json['name']?.toString();
}
Map<String, dynamic> toJson() {
'age' = age;
'image' = image;
'name' = name;
}
}
因此,当您解析 http 响应时,现在您所要做的就是,
People.fromJson(json.decode(response.body));
这样您可以保留 json 并在克隆人员列表时,您所要做的就是,
// With the following line _people will now be new list with new objects but with mutated _people data
_people = _people.map((e) => People.fromJson(e.toJson())).toList();
// With the following line _people will now be new list with new objects but with data which we have recieved from the API call
_people = _people.map((e) => People.fromJson(e.originalJson)).toList();
这种维护 class 的方法肯定能帮到您..