You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用对象A重置复杂对象B?Dart代码中用户列表未同步刷新问题排查

问题分析与解决方案

你遇到的问题核心在于浅拷贝(Shallow Copy)和引用类型的特性,咱们一步步拆解清楚:

为什么用户信息没刷新?

Dart 里的 List.from() 方法处理引用类型(比如你定义的 User 类)时,只会复制列表中对象的内存引用地址,而不是创建全新的 User 实例。也就是说:

  • 当你执行 b.users = List<User>.from(a.users!); 时,b.users 里的 User 对象和 a.users 里的是同一个内存地址的对象
  • 所以你修改 b.users![0].name = 'Doe' 时,其实是直接修改了 a.users 里那个 User 对象的 name 属性
  • 后续调用 resetTask(a) 时,你只是把 a.users 的引用再次复制给 b.users,但此时 a 里的 User 的 name 已经是 Doe 了,自然输出的还是 Doe

解决方法:实现深拷贝

要让 b 的 users 列表和 a 的完全独立,需要做深拷贝——为每个 User 创建新的实例,而不是复制引用。修改 resetTask 方法里的列表复制逻辑即可:

void main() {
  Task a = Task(id: 1, title:'task 1', users: [User(id:0, name:'John')]);
  Task b = Task(id: a.id, title: a.title, users: List<User>.from(a.users!));
  
  resetTask(Task task) {
    b.id = task.id;
    b.title = task.title;
    // 替换成深拷贝:为每个User创建新实例
    b.users = task.users!.map((user) => User(id: user.id, name: user.name)).toList();
  }
  
  print(b.title); // task 1
  print('${b.users![0].name} \n'); // John
  
  b.title = 'task 2';
  b.users![0].name = 'Doe';
  print(b.title); // task 2
  print('${b.users![0].name} \n'); // Doe
  
  resetTask(a);
  print(b.title); // task 1
  print('${b.users![0].name} \n'); // John
}

class Task {
  Task({this.id, this.title, this.users});
  int? id;
  String? title;
  List<User>? users;
}

class User {
  User({this.id, this.name});
  int? id;
  String? name;
}

验证结果

修改后运行代码,控制台输出会完全符合你的预期:

task 1
John 

task 2
Doe 

task 1
John 

内容的提问来源于stack exchange,提问作者rigorousCode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 14:07:32