skip to Main Content

How to set New Variable value from Old Variable value, if New Variable value changed the Old Variable not follow the changes. with Condition of type Data is Object?
I actually asked about this problem here

But the problem I found confused me. Just look for the example code:

void main() {
  final Data mainData = Data(
    data: [
      Group(
        id: 1,
        groupName: 'Assault Riffle',
        weaponItems: [
          Weapon(id: 1, name: 'Ak47'),
          Weapon(id: 2, name: 'M4'),
        ],
      ),
      Group(
        id: 2,
        groupName: 'SMG',
        weaponItems: [
          Weapon(id: 3, name: 'MP5'),
          Weapon(id: 4, name: 'Dual UZI'),
        ],
      ),
    ],
  );

  final Data newData = Data(data: mainData.data); // create new Instance
  print('before mainData: ${mainData.data?[0].weaponItems?[0].name}'); // mainData: Ak47
      
  newData.data?[0].weaponItems?[0].name = 'SCAR';

  print('newData: ${newData.data?[0].weaponItems?[0].name}'); // newData: SCAR
  print('after mainData: ${mainData.data?[0].weaponItems?[0].name}'); // mainData: Scar (should Ak47)
}

As you can see the newData that I changed made the data in mainData change even though I had created a new instance.

The model data class:

class Data {
  List<Group>? data;

  Data({this.data});
}

class Group {
  int? id;
  List<Weapon>? weaponItems;
  String? groupName;

  Group({
    this.id,
    this.weaponItems,
    this.groupName,
  });
}

class Weapon {
  int? id;
  String? name;

  Weapon({this.id, this.name});
}

How to solve this problem?

3

Answers


  1. Your problem is how you access the data. When you copy an array in dart you don’t copy it but you actually copy the pointer to the array.
    Copy your array elements 1 by 1 and you won’t have this problem anymore.

    Replace your :

    final Data newData = Data(data: mainData.data); // create new Instance
    

    by

    final Data newData = Data();
    for(Group group in mainData.data){ 
     newData.data.add(group); 
    }
    
    Login or Signup to reply.
  2. You need to make a deep copy of the structure to do what you want to do. This is a way to do it:

    final Data newData = Data(
        data: mainData.data
            ?.map((group) => Group(
                id: group.id,
                weaponItems: group.weaponItems
                    ?.map((weapon) => Weapon(id: weapon.id, name: weapon.name))
                    .toList(),
                groupName: group.groupName))
            .toList());
    
    Login or Signup to reply.
  3. i created adjustment to your modelling and create custom function like copyWith and replaceWeapon, it will come handy if you need to change something.

    the result :

    final Data mainData = Data(
        data: [
          Group(
            id: 1,
            groupName: 'Assault Riffle',
            weaponItems: [
              Weapon(id: 1, name: 'Ak47'),
              Weapon(id: 2, name: 'M4'),
            ],
          ),
          Group(
            id: 2,
            groupName: 'SMG',
            weaponItems: [
              Weapon(id: 3, name: 'MP5'),
              Weapon(id: 4, name: 'Dual UZI'),
            ],
          ),
        ],
      );
    
      final Data newData = mainData.copyAndReplaceWeaponAt(
          indexGroup: 0, indexWeapon: 0, newWeapon: Weapon(name: 'SCAR'));
    
      print('newData: ${newData.data[0].weaponItems[0].name}'); // newData: SCAR
      print('after mainData: ${mainData.data[0].weaponItems[0].name}'); //----> AK47
    

    modelling :

    class Data {
      final List<Group> data;
      Data({List<Group>? data}) : data = data ?? [];
    
      Data copyAndReplaceWeaponAt(
          {required int indexGroup,
          required int indexWeapon,
          required Weapon newWeapon}) {
        return Data(
            data: List.generate(data.length, (index) {
          if (index == indexGroup) {
            List<Weapon> weapons =
                List.generate(data[indexGroup].weaponItems.length, (index) {
              if (index == indexWeapon) {
                return data[indexGroup]
                    .weaponItems[indexWeapon]
                    .copyWith(id: newWeapon.id, name: newWeapon.name);
              }
              return data[indexGroup].weaponItems[index];
            });
            return data[index].copyWith(weaponItems: weapons);
          }
          return data[index];
        }));
      }
    }
    
    class Group {
      final int? id;
      final List<Weapon> weaponItems;
      final String? groupName;
    
      Group({this.id, this.groupName, List<Weapon>? weaponItems})
          : weaponItems = weaponItems ?? [];
    
      Group copyWith({
        int? id,
        List<Weapon>? weaponItems,
        String? groupName,
      }) {
        return Group(
            id: id ?? this.id,
            weaponItems: weaponItems ?? this.weaponItems,
            groupName: groupName ?? this.groupName);
      }
    }
    
    class Weapon {
      final int? id;
      final String? name;
    
      Weapon({this.id, this.name});
    
      Weapon copyWith({
        int? id,
        String? name,
      }) {
        return Weapon(id: id ?? this.id, name: name ?? this.name);
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search