- Published on
Flutter Dart 深拷贝全方案:Map 与实体类全解析
- Authors

- 作者
- kai
目录

Dart 深拷贝全方案:Map 与实体类全解析
在 Web 开发中,JSON.parse(JSON.stringify(obj)) 是实现深拷贝的常用方案(函数等特殊类型除外)。而在 Dart 中,深拷贝场景同样高频,尤其涉及 Map 和实体类时。Dart 没有内置通用深拷贝 API,本文结合 Dart 3.x 特性,整理一套实用方案,覆盖主流场景。
一、Map 集合的深拷贝
Map 深拷贝需区分基础类型和嵌套复杂类型,适配不同方案:
1. 基础方案:JSON 序列化拷贝
最贴近 Web 开发思路,通过 jsonEncode 转字符串再用 jsonDecode 解析,适合简单 Map:
import 'dart:convert';
void main() {
Map<String, dynamic> originalMap = {
'name': '张三',
'age': 25,
'hobbies': ['篮球', '编程']
};
// 深拷贝
Map<String, dynamic> clonedMap = jsonDecode(jsonEncode(originalMap)) as Map<String, dynamic>;
// 验证独立性
clonedMap['age'] = 30;
clonedMap['hobbies'].add('阅读');
print('原始:$originalMap 拷贝后:$clonedMap');
}
优缺点:
优点:代码简洁,无依赖,适合简单结构;
缺点:不支持函数、
DateTime等特殊类型(会丢失类型信息)。
2. 手动遍历拷贝(复杂嵌套场景)
当 Map 嵌套自定义对象时,手动遍历逐层拷贝更安全:
class Person {
String name;
int age;
Person(this.name, this.age);
// 自定义拷贝方法
Person.copy(Person other) : name = other.name, age = other.age;
String toString() => 'Person($name, $age)';
}
void main() {
Map<String, Person> personMap = {
'user1': Person('李四', 28),
'user2': Person('王五', 32)
};
// 深拷贝
Map<String, Person> clonedMap = personMap.map((k, v) => MapEntry(k, Person.copy(v)));
clonedMap['user1']?.name = '赵六';
print('原始:$personMap 拷贝后:$clonedMap');
}
3. 第三方工具:deepcopy 包
多层嵌套集合(Map/List/Set 混合)推荐用 deepcopy 包,支持递归拷贝:
安装依赖:
dependencies:
deepcopy: ^1.1.2
使用示例:
import 'package:deepcopy/deepcopy.dart';
void main() {
Map<String, dynamic> complexMap = {
'user': {'name': '孙七', 'age': 26},
'friends': [{'name': '周八'}, {'name': '吴九'}]
};
Map<String, dynamic> clonedMap = complexMap.deepCopy();
clonedMap['user']['name'] = '郑十';
print('原始:$complexMap 拷贝后:$clonedMap');
}
二、实体类的深拷贝
自定义实体类是 Flutter 开发核心,深拷贝需兼顾简洁性和嵌套场景:
1. 基础方案:JSON 序列化转实体
通过 fromJson 和 toJson 配合 JSON 序列化,适合简单实体:
import 'dart:convert';
class ApiResponse {
final int code;
final String? message;
ApiResponse({required this.code, this.message});
// 从JSON构建
ApiResponse.fromJson(Map<String, dynamic> json)
: code = json['code'] as int,
message = json['message'] as String?;
// 转为JSON
Map<String, dynamic> toJson() => {'code': code, 'message': message};
}
void main() {
final original = ApiResponse(code: 200, message: '成功');
// 深拷贝
final cloned = ApiResponse.fromJson(original.toJson());
}
缺点:嵌套实体需逐层处理,不支持 DateTime 等特殊类型。
2. 进阶方案:自定义拷贝构造函数
复杂嵌套实体推荐用拷贝构造函数,精准控制拷贝逻辑:
class Address {
String city;
Address({required this.city});
// 拷贝构造函数
Address.copy(Address other) : city = other.city;
}
class User {
String name;
Address address;
User({required this.name, required this.address});
// 嵌套拷贝
User.copy(User other) : name = other.name, address = Address.copy(other.address);
}
void main() {
final original = User(name: '钱十一', address: Address(city: '深圳'));
final cloned = User.copy(original);
cloned.address.city = '广州'; // 不影响原始对象
}
3. 高效方案:注解工具(如 dart_mappable)
大型项目推荐用注解工具自动生成代码,支持嵌套拷贝:
安装依赖:
dependencies:
dart_mappable: ^4.2.2
dev_dependencies:
build_runner: ^2.4.0
dart_mappable_builder: ^4.2.2
定义实体并生成代码:
()
class Product with ProductMappable {
final String name;
final double price;
Product({required this.name, required this.price});
}
// 执行命令生成代码:dart run build_runner build
使用示例:
void main() {
final original = Product(name: '教程', price: 99.0);
// 拷贝并修改
final cloned = original.copyWith(name: '深拷贝教程');
}
三、方案选型建议
| 方案 | 适用场景 | 核心优势 |
|---|---|---|
| JSON 序列化 | 简单 Map/实体类 | 简洁无依赖 |
| 手动拷贝构造函数 | 复杂嵌套实体类 | 类型安全,控制精准 |
| deepcopy 包 | 复杂嵌套集合 | 一键递归拷贝 |
| dart_mappable 注解 | 大型项目、多嵌套实体 | 自动生成代码,支持链式拷贝 |
四、注意事项
- 空安全:Dart 3.x 强制空安全,拷贝时需处理可选参数;
- 特殊类型:
DateTime等需手动转换(如序列化时转时间戳); - 性能:JSON 序列化在大数据量场景性能较差,优先选注解工具或手动拷贝。
