I have a list of maps which are initialized as follow
List<dynamic> _people = [];
Map<String, dynamic> _person = {
'image' : null,
'name': null,
'age': null
};
On one of the methods inside the program I intend to copy the value inside _people
to a new List variable so I can make changes to it.
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;
}
}
Now the problem here is that everytime I assign the value of img
to _peopleCopy
, it would change the respective value on _people
list as well even though I did List.from()
method to clone it. Obviously, I wanted to preserve the original content of _people
list. What did I do wrong here?
CodePudding user response:
You have successfully created a new list. But the list contains the references to the same maps. So changing a map will change it in both lists since it's the same element.
You need to copy the elements, too.
Since your map also contains a dynamic
type that you probably want to deep copy, I would suggest to just jsonEncode
/jsonDecode
your whole structure. Serializing and Deserializing is not the most efficient way, but it will create a deep copy of whatever structure is in there.
That said, Dart is a real programming language. It helps a lot to use it that way. If you use actual types, instead of dynamic
, it becomes less guessing, praying and duct-typing and more solid, fact based programming. Since this seem to be JSON structures, use model classes. Then you can have your own deep copy methods and have compiler support that you just don't get when you use dynamic
.
CodePudding user response:
For such case what I do is, I store the originalJson of the object inside a variable in the object class like below,
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;
}
}
So when you are parsing the http reponse, now all you have to do is,
People.fromJson(json.decode(response.body));
This way you can preserve the json and while cloning the list of People, all you have to do is,
// 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();
This way of maintaining the class should for sure help you out..