5.1 什么是数据模型?
数据模型(Model) 是用来描述应用数据的类。它定义了:
- 数据有哪些属性(字段)
- 每个属性的类型
- 如何创建、修改、转换数据
类比理解
想象你要设计一个数据库表来存储任务信息:
1CREATE TABLE tasks (
2 id TEXT PRIMARY KEY,
3 title TEXT NOT NULL,
4 is_completed BOOLEAN DEFAULT FALSE,
5 created_at DATETIME,
6 due_date DATETIME
7);在 Flutter 中,我们用 Dart 类来实现同样的功能:
class Task {
final String id;
final String title;
final bool isCompleted;
final DateTime createdAt;
final DateTime? dueDate;
}5.2 Task 类的完整代码
/// Task Model
/// Represents a single todo item with its properties
class Task {
/// Unique identifier for the task
final String id;
/// Title/description of the task
final String title;
/// Whether the task is completed
final bool isCompleted;
/// Timestamp when the task was created
final DateTime createdAt;
/// Optional due date for the task
final DateTime? dueDate;
Task({
required this.id,
required this.title,
this.isCompleted = false,
required this.createdAt,
this.dueDate,
});
/// Create a copy of this task with modified fields
Task copyWith({
String? id,
String? title,
bool? isCompleted,
DateTime? createdAt,
DateTime? dueDate,
}) {
return Task(
id: id ?? this.id,
title: title ?? this.title,
isCompleted: isCompleted ?? this.isCompleted,
createdAt: createdAt ?? this.createdAt,
dueDate: dueDate ?? this.dueDate,
);
}
/// Convert Task to JSON for local storage
Map toJson() {
return {
'id': id,
'title': title,
'isCompleted': isCompleted,
'createdAt': createdAt.toIso8601String(),
'dueDate': dueDate?.toIso8601String(),
};
}
/// Create Task from JSON (from local storage)
factory Task.fromJson(Map json) {
return Task(
id: json['id'] as String,
title: json['title'] as String,
isCompleted: json['isCompleted'] as bool,
createdAt: DateTime.parse(json['createdAt'] as String),
dueDate: json['dueDate'] != null
? DateTime.parse(json['dueDate'] as String)
: null,
);
}
@override
String toString() {
return 'Task(id: $id, title: $title, isCompleted: $isCompleted)';
}
}
/// Filter types for task list
enum TaskFilter {
all('全部'),
active('进行中'),
completed('已完成');
final String label;
const TaskFilter(this.label);
}5.3 逐行解析
类定义和属性
class Task {
final String id; // 任务唯一标识
final String title; // 任务标题
final bool isCompleted; // 是否已完成
final DateTime createdAt; // 创建时间
final DateTime? dueDate; // 截止日期(可为空)关键字解释:
| 关键字 | 含义 | 说明 |
|---|---|---|
final |
不可变 | 赋值后不能修改 |
String |
字符串类型 | 存储文本 |
bool |
布尔类型 | true/false |
DateTime |
日期时间类型 | 存储时间 |
DateTime? |
可空的日期时间 | ? 表示可为 null |
构造函数
Task({
required this.id,
required this.title,
this.isCompleted = false,
required this.createdAt,
this.dueDate,
});语法解析:
{}包裹的参数是命名参数,调用时必须指定参数名required表示该参数必须提供this.isCompleted = false表示有默认值 falsethis.dueDate没有 required 也没有默认值,表示可选(可为 null)
使用示例:
// 创建一个新任务
final task = Task(
id: 'abc-123',
title: '买牛奶',
createdAt: DateTime.now(),
dueDate: DateTime.now().add(Duration(days: 1)),
);
// isCompleted 使用默认值 falsecopyWith 方法
Task copyWith({
String? id,
String? title,
bool? isCompleted,
DateTime? createdAt,
DateTime? dueDate,
}) {
return Task(
id: id ?? this.id,
title: title ?? this.title,
isCompleted: isCompleted ?? this.isCompleted,
createdAt: createdAt ?? this.createdAt,
dueDate: dueDate ?? this.dueDate,
);
}为什么需要 copyWith?
因为 final 字段创建后不能修改,所以要用 copyWith 创建一个新的 Task,只改变需要的字段。
使用示例:
final task = Task(
id: 'abc-123',
title: '买牛奶',
createdAt: DateTime.now(),
);
// 标记为已完成(创建新对象,不修改原对象)
final completedTask = task.copyWith(isCompleted: true);
print(task.isCompleted); // false(原对象不变)
print(completedTask.isCompleted); // true(新对象已改变)?? 运算符:
id ?? this.id表示:如果 id 不为 null,使用 id;否则使用 this.id。
toJson 方法
Map toJson() {
return {
'id': id,
'title': title,
'isCompleted': isCompleted,
'createdAt': createdAt.toIso8601String(),
'dueDate': dueDate?.toIso8601String(),
};
}作用: 将 Task 对象转换为 JSON 格式,用于本地存储。
返回类型: Map 是一个键值对映射:
String是键的类型(属性名)dynamic是值的类型(可以是任意类型)
DateTime.toIso8601String():
将日期时间转换为标准格式的字符串,例如:
2024-01-15T10:30:00.000?. 运算符:
dueDate?.toIso8601String()表示:如果 dueDate 不为 null,调用 toIso8601String();否则返回 null。
fromJson 工厂方法
factory Task.fromJson(Map json) {
return Task(
id: json['id'] as String,
title: json['title'] as String,
isCompleted: json['isCompleted'] as bool,
createdAt: DateTime.parse(json['createdAt'] as String),
dueDate: json['dueDate'] != null
? DateTime.parse(json['dueDate'] as String)
: null,
);
}作用: 从 JSON 数据创建 Task 对象,用于从本地存储读取数据。
关键字解释:
factory- 工厂构造函数,可以返回现有实例或子类as String- 类型转换,将 dynamic 转换为 StringDateTime.parse()- 将字符串解析为 DateTime 对象
使用示例:
// 假设从存储读取的 JSON 数据
final json = {
'id': 'abc-123',
'title': '买牛奶',
'isCompleted': false,
'createdAt': '2024-01-15T10:30:00.000',
'dueDate': null,
};
// 转换为 Task 对象
final task = Task.fromJson(json);toString 方法
@override
String toString() {
return 'Task(id: $id, title: $title, isCompleted: $isCompleted)';
}作用: 定义对象转换为字符串的格式,方便调试打印。
使用示例:
final task = Task(id: '123', title: '测试', createdAt: DateTime.now());
print(task); // 输出: Task(id: 123, title: 测试, isCompleted: false)5.4 TaskFilter 枚举
enum TaskFilter {
all('全部'),
active('进行中'),
completed('已完成');
final String label;
const TaskFilter(this.label);
}什么是枚举?
枚举(Enum)是一种定义固定值集合的方式。
使用示例:
// 获取当前筛选条件
TaskFilter filter = TaskFilter.all;
// 获取显示标签
print(filter.label); // 输出: 全部
// 比较
if (filter == TaskFilter.completed) {
print('显示已完成任务');
}
// 遍历所有值
for (var filter in TaskFilter.values) {
print(filter.label);
}5.5 完整使用示例
void main() {
// 1. 创建任务
final task1 = Task(
id: 'task-001',
title: '学习 Flutter',
createdAt: DateTime.now(),
dueDate: DateTime.now().add(Duration(days: 7)),
);
final task2 = Task(
id: 'task-002',
title: '买牛奶',
createdAt: DateTime.now(),
);
print('创建的任务:');
print(task1);
print(task2);
// 2. 修改任务(使用 copyWith)
final completedTask = task1.copyWith(isCompleted: true);
print('\n标记为完成:');
print(completedTask);
// 3. 转换为 JSON(保存到本地)
final json = task1.toJson();
print('\nJSON 格式:');
print(json);
// 4. 从 JSON 恢复
final restoredTask = Task.fromJson(json);
print('\n恢复的任务:');
print(restoredTask);
// 5. 使用筛选枚举
TaskFilter currentFilter = TaskFilter.active;
print('\n当前筛选: ${currentFilter.label}');
}输出:
创建的任务:
Task(id: task-001, title: 学习 Flutter, isCompleted: false)
Task(id: task-002, title: 买牛奶, isCompleted: false)
标记为完成:
Task(id: task-001, title: 学习 Flutter, isCompleted: true)
JSON 格式:
{id: task-001, title: 学习 Flutter, isCompleted: false, createdAt: 2024-01-15T10:30:00.000, dueDate: 2024-01-22T10:30:00.000}
恢复的任务:
Task(id: task-001, title: 学习 Flutter, isCompleted: false)
当前筛选: 进行中5.6 小结
| 概念 | 作用 |
|---|---|
final |
定义不可变属性 |
required |
标记必须传入的参数 |
? |
标记可为 null 的类型 |
copyWith |
创建修改后的副本 |
toJson |
转换为 JSON 格式 |
fromJson |
从 JSON 创建对象 |
enum |
定义固定值集合 |
下一步:第六章:状态管理详解