Appearance
单例
在Flutter的开发过程中,一个完整的项目,几乎少不了的使用到单例模式,为什么这么说,如果你使用网络请求。那么你一定会基于Dio或者任何的网络请求库实现自己的请求类。对此你一定会用到单例。如果你并没有为所有的请求封装一个统一的请求类,或者即便实现也不使用单例,那么你大错特错。
单例可以帮助你减少一个类的构造函数重复的调用,同时可以节省不断new一个对象时,创建出的内存。
以我们的RequestClient类为示例,
dart
class RequestClient {
final Dio _dio = Dio();
// context
final BuildContext? context;
/// 是否自动添加 票据
final bool autoAuthorization;
RequestClient({this.context, this.autoAuthorization = true}) {
/// 我们会在这里进行一些初始化操作,比如接口配置
/// 此外还会添加请求时的interceptors,以及响应的interceptors
/// 如果不使用单例,这些构造函数将不断地被重复初始化
}
/// ...get 方法封装
/// ...post 方法封装
}
而当我们加入单例后,在来调用RequestClient时,我们只需要调用RequestClient.instance即可。
dart
class Request {
/// 工厂模式
static Request get instance => _getInstance();
static Request? _instance;
/// 后端并未处理无效token,所以只能前端保留2个实例在整个应用的生命周期
RequestClient? client;
Request._internal();
static Request _getInstance() {
_instance ??= Request._internal();
return _instance!;
}
factory Request({BuildContext? context}) {
if (_getInstance().client == null) {
_getInstance().client =
RequestClient(context: context, autoAuthorization: true);
}
return _getInstance();
}
void reset() {
_getInstance().client = null;
}
}
当上面的请求类通过下面的方式调用时,将不再被重复初始化
dart
Future<void> run()async {
await Request().client!.get("url-1");
await Request().client!.get("url-2");
}
run();
如何实现单例
在 Dart 的空安全特性下,可以使用 late
关键字和静态变量来创建一个空安全的单例模式。下面是一个示例代码:
dart
class Singleton {
static late Singleton _instance;
Singleton._();
factory Singleton() {
_instance ??= Singleton._();
return _instance;
}
// 其他实例方法和属性...
}
在上述代码中,late
关键字用于初始化 _instance
变量。late
关键字表示该变量会延迟初始化,使得在构造函数调用时不需要立即给 _instance
赋值。通过使用 ??=
运算符,只有当 _instance
为空时才会进行实例化,从而保证只有一个实例被创建。
使用空安全的单例模式时,可以通过以下方式访问单例对象:
dart
var singleton = Singleton();
每次调用 Singleton()
都会返回同一个实例,即全局唯一的实例。
在 Dart 的空安全模式下,还可以使用 late
关键字配合 static
关键字来实现静态的空安全单例模式。示例如下:
dart
class Singleton {
static late final Singleton _instance = Singleton._();
Singleton._();
static Singleton get instance => _instance;
// 其他实例方法和属性...
}
在上述代码中,通过将 _instance
声明为 late final
,并使用 static
修饰其访问器 instance
,实现了一个静态的空安全单例模式。通过 Singleton.instance
可以访问到单例对象。
使用空安全的单例模式时,需要注意合理设计单例的初始化和使用方式,以避免空引用错误和不必要的实例化。空安全的特性能够在编译时帮助捕捉潜在的空引用异常,让代码更加健壮和可靠。