【问题标题】:Flutter Clone a List inside ChangeNotifier objectFlutter 在 ChangeNotifier 对象中克隆一个列表
【发布时间】:2021-05-21 08:42:02
【问题描述】:

我正在使用提供程序包作为状态管理解决方案,效果很好。

负责在整个应用程序中提供数据的主要对象具有列表变量。 它是一个扩展的 ChangeNotifier 对象,如下所示:

class DataSource with ChangeNotifier {...}

我有 setter 和 getter 来管理变量。

当我尝试在 DataSource 类的函数内克隆列表变量时,它实际上从未克隆列表。

void cloneList() {
  List<dynamic> list1 = [[Jack, 0], [Jane, 1]];
  List<dynamic> list2 = List.from(list1);
  list2.shuffle();
  print(list1);
  print(list2);

list1 和 list2 是完全相同的表!

关于这个问题的有趣之处在于,当我在我的无状态小部件中执行相同的操作时它运行良好!

我只能找到两个操作之间的一个区别;

  1. 带有 ChangeNotifier 的对象变量
  2. 实例变量

你有什么办法解决这个问题吗?

注意:作为一个很好的解决方案是使用 List.Generate 函数创建另一个列表,但它很难管理。

非常感谢您。

【问题讨论】:

    标签: list flutter dart


    【解决方案1】:

    问题是List.from(...) 执行浅拷贝。 list1list2 的内容仍然引用相同的对象 [Jack, 0][Jane, 1]

    void main() {
      String jack = 'Jack';
      String jane = 'Jane';
      final listOne = [[jack, 0], [jane, 1]];
      final listTwo = List.from(listOne);
      listOne[0][0] = 'Arthur';
      listOne[0][1] = '123';
      print(listOne); // [[Arthur, 123], [Jane, 1]]
      print(listTwo); // [[Arthur, 123], [Jane, 1]]
    }
    

    一种解决方案:不变性

    使用Freezed package,我使我的Person 类不可变。

    现在,我无法更改Personage,而是必须将Person 复制为age 的新值。

    import 'package:freezed_annotation/freezed_annotation.dart';
    
    part '66259238.freezed.freezed.dart';
    
    void main() {
      Person jack = Person(name: 'Jack', age: 42);
      Person jane = Person(name: 'Jane', age: 36);
      List<Person> list1 = [jack, jane];
      List<Person> list2 = [...list1];
      // list1[0].age = 36; // COMPILATION ERROR: There isn’t a setter named 'age' in class '_$Person'.
      list1[0] = list1[0].copyWith(age: 43);
      print(list1); // [Person(name: Jack, age: 43), Person(name: Jane, age: 36)]
      print(list2); // [Person(name: Jack, age: 42), Person(name: Jane, age: 36)]
    }
    
    @freezed
    abstract class Person with _$Person {
      const factory Person({String name, int age}) = _Person;
    }
    

    【讨论】:

    • 这个解决方案比我的好。但必须存在更好的解决方案。如何防止对象内列表变量的浅拷贝。我的应用程序的性质需要许多这样的操作,它对内存很友好但并不容易,并且涵盖了我的所有需求。如果可能的话,我想使用像 List.from(...) 这样非常简单的方法。
    • 如果您愿意,可以使用list2 = List.from(list1); 代替list2 = [...list1];。只有当您修改 Person 时,您才需要使用 copyWith 来尊重不变性。
    猜你喜欢
    • 2018-11-27
    • 1970-01-01
    • 2019-03-25
    • 1970-01-01
    • 2017-04-11
    • 1970-01-01
    • 2013-10-11
    • 2015-04-25
    • 1970-01-01
    相关资源
    最近更新 更多