0

I have seen a few questions on this topic but have not found an answer. Given the following code I am trying to create a copy of the "kids" List from one instance to another. For Strings this works however for List it is only a reference and when I update the value of kids in the 2nd instance it also updates in the first. My code is below.

import 'package:flutter/material.dart';
import './screens/detail_screen.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Person person1 = Person();
  List<Person> people = [];

  @override
  void initState() {
    super.initState();
    person1.firstName = 'Jack';
    person1.kids = [
      {'Karen': 'girl'},
      {'Bob': 'girl'}
    ];
    people.add(person1);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView.builder(
        itemCount: people.length,
        itemBuilder: (context, int index) {
          return ListTile(
            title: Text(
              '${people[index].firstName}',
            ),
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => DetailsScreen(people[index]),
                ),
              );
            },
          );
        },
      ),
    );
  }
}

class Person {
  String firstName;
  List kids;
}

class DetailsScreen extends StatefulWidget {
  final Person person;
  DetailsScreen(this.person);
  @override
  _DetailsScreenState createState() => _DetailsScreenState();
}

class _DetailsScreenState extends State<DetailsScreen> {
  static final TextEditingController _textController = TextEditingController();

  Person newPerson = Person();

  @override
  void initState() {
    super.initState();
    newPerson.firstName = widget.person.firstName;
    _textController.text = widget.person.firstName;
  }

  updateName(newName) {
    newPerson.firstName = newName;
// This is where I am trying to copy the value of "kids".
    newPerson.kids = List.from(widget.person.kids);
    newPerson.kids[1]['Bob'] = 'boy';
    print(newPerson);
    print(widget.person);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
            icon: Icon(
              Icons.close,
              color: Colors.white,
            ),
            onPressed: () {
              Navigator.pop(context);
            }),
        actions: <Widget>[
          IconButton(
              icon: Icon(
                Icons.check,
                color: Colors.white,
              ),
              onPressed: () {
                updateName(_textController.text);
              }),
        ],
      ),
      body: Center(
        child: TextField(
          controller: _textController,
        ),
      ),
    );
  }
}

Is there a way of doing this? If not what is best practice to achieve the same result? I have read this article but it refers to Strings and not Lists. How to clone (copy values) a complex object in Dart 2

dwax
  • 381
  • 7
  • 19
  • Does this answer your question? [How to copy List in dart without old reference?](https://stackoverflow.com/questions/50460367/how-to-copy-listt-in-dart-without-old-reference) – 呂學洲 Jun 25 '21 at 01:33

2 Answers2

2

Can you try this:

First import dart convert top of the page like this

import 'dart:convert';

Then update your updateName method with this one

updateName(newName) {
newPerson.firstName = newName;
List<dynamic> newPersonKids = jsonDecode(jsonEncode(widget.person.kids));
newPerson.kids = newPersonKids;
newPerson.kids[1]['Bob'] = 'boy';}
Ulaş Kasım
  • 810
  • 1
  • 8
  • 14
-1

List.from(list) should work for creating a new instance of the list.

You can try this in the https://dartpad.dev/

final list = [0,1,2];
final newList = list;
print(newList);
list[0] = 55;
print(newList); //here, newList is changed because it is an instance of list

Result: [0,1,2] [55, 1, 2]

What you would expect:

final list = [0,1,2];
final newList = List.from(list);
print(newList);
list[0] = 55;
print(newList); //here, newList has no change because it is a new instance

Result: [0,1,2] [0,1,2]

Danilo Rêgo
  • 539
  • 5
  • 4