异步构造函数
本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 79 课,共 110 课。
Dart 中的构造函数不能标记为 async,因为它们必须立即返回类的实例,而不是 Future。那么,如何创建需要异步初始化的对象呢?例如,需要从数据库加载数据或获取配置的对象。
解决方案是使用静态异步工厂方法。将构造函数设为私有(或保持简单),并提供一个执行异步操作并返回类的 Future 的静态方法:
class UserProfile {
final String name;
final int age;
UserProfile._(this.name, this.age); // 私有构造函数
static Future<UserProfile> create(String userId) async {
// 模拟获取数据
await Future.delayed(Duration(seconds: 1));
return UserProfile._('Alice', 25);
}
}
Future<void> main() async {
var user = await UserProfile.create('123');
print(user.name); // Alice
}私有构造函数 UserProfile._ 负责实际创建对象,而静态 create() 方法负责处理所有异步工作。调用方使用 await 获取完全初始化的对象。
这种模式可以确保你拿到对象后,它已经完全可以使用,不会处于未完成初始化或缺少数据的状态。它通常用于需要加载资源、连接服务或执行耗时设置的类。
挑战
简单我们来构建一个配置加载器,看看如何处理类中的异步初始化!由于构造函数不能是异步的,你将使用静态工厂方法模式来创建需要时间“加载”数据的对象。
你将把代码分成两个文件:
config_loader.dart:创建一个ConfigLoader类,模拟异步加载配置设置。这个类应包含:- 三个 final 字段:
appName(String)、version(String)和maxUsers(int) - 一个用于初始化这三个字段的私有构造函数
- 一个名为
load的静态异步工厂方法,它接收一个String configId参数,并返回Future<ConfigLoader>。这个方法应当:- 使用
Future.delayed(),并设置 100 毫秒的延迟来模拟加载所需的时间 - 根据
configId生成配置值:appName:在 configId 后面拼接" App"version:在"1.0."后面接上 configId 的长度maxUsers:configId 的长度乘以 10
- 使用这些值返回一个新的
ConfigLoader实例
- 使用
- 一个
displayInfo()方法,按以下格式输出配置:Config: [appName] v[version] (max [maxUsers] users)
- 三个 final 字段:
main.dart:导入配置加载器,并演示异步初始化模式:- 输出
Loading configurations... - 使用 configId
"Production"加载配置,并调用它的displayInfo() - 使用 configId
"Dev"加载配置,并调用它的displayInfo() - 输出
All configs loaded!
- 输出
注意,静态 load 方法负责处理所有异步操作,而私有构造函数只负责赋值。调用方使用 await 来获取完全初始化的对象!
预期输出:
Loading configurations...
Config: Production App v1.0.10 (max 100 users)
Config: Dev App v1.0.3 (max 30 users)
All configs loaded!亲手试试
import 'config_loader.dart';
void main() async {
// TODO: 打印 "Loading configurations..."
// TODO: 加载 configId 为 "Production" 的配置
// 并调用它的 displayInfo() 方法
// TODO: 加载 configId 为 "Dev" 的配置
// 并调用它的 displayInfo() 方法
// TODO: 打印 "All configs loaded!"
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器