新列表在克隆后仍然引用旧列表

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 的方法肯定能帮到您..