Flutter单例模式实现插件singleton的使用
Flutter单例模式实现插件singleton的使用
Singleton 是一个非常有用的模式,在Flutter应用中可以帮助我们优化对象的实例化。它可以减少内存浪费,提高应用加载速度,并且可以在多个地方复用同一个对象。
为什么创建这个库
Singleton 模式可以用于以下场景:
- 延迟实例化对象以加速应用加载。
- 按需实例化对象,减少未使用的对象占用的内存。
- 对象创建复杂或依赖于某些资源,但在整个应用中广泛使用。
- 对象依赖异步资源,但需要同步方式使用。
但是有时候使用 Singleton 模式会带来一些麻烦,比如:
- 每次使用时都需要手动实现延迟模式,这很繁琐。
Singleton不利于单元测试,因为它们在整个测试过程中存在,可能会导致意外的测试失败。- 依赖异步资源的
Singleton管理起来比较复杂。
Singleton 库旨在简化这些场景,使开发者能够更优雅地在 Dart 中使用 Singleton。
这个库能做什么
该库主要支持三种类型的 Singleton 使用:
- 惰性单例:类型按需延迟创建。它类似于 Kotlin 的
lazy委托属性。 - 急切单例:类型创建复杂或依赖于某些仅在特定情况下可用的资源,因此提前创建实例是个好主意。
- 未来单例:类型依赖于异步资源进行实例化,但需要在强制同步的环境中使用。
- 允许为测试重置所有注册的
Singleton,从而减轻跨测试污染。
该库设计时考虑了 Flutter,但它不依赖任何 Flutter 特定的代码,因此可以在任何 Dart 工作的地方使用。
惰性单例
手动实现惰性单例
你可能会多次编写类似的代码:
class MyLazyService {
static MyLazyService _instance;
static MyLazyService get instance {
if (_instance == null) {
_instance = MyLazyService._();
}
return _instance;
}
/// 私有构造函数
MyLazyService._() {
}
/// 执行某些操作
void doSomething() {
}
}
MyLazyService.instance.doSomething();
这种方法虽然可行,但写起来很枯燥,而且会影响测试。
使用 Singleton 实现惰性单例
class MyLazyService {
/// 工厂方法自动复用相同的实例
factory MyLazyService() => Singleton.lazy(() => MyLazyService._()).instance;
/// 私有构造函数
MyLazyService._() {}
/// 执行某些操作
void doSomething() {}
}
MyLazyService().doSomething(); // 看起来像新的实例,但实际上是一个单例。
急切单例
class MyEagerService {
/// 工厂方法自动复用相同的实例
factory MyEagerService() => Singleton<MyEagerService>().instance;
final MyApi api;
/// 构造函数创建并注册新实例
MyEagerService.initialize(this.api) {
// 注册当前实例
Singleton.register(this);
}
/// 执行某些操作
void doSomething() {}
}
void main() {
final appSettings = getAppSettings();
final httpClient = createHttpClient(appSetting);
final api = createApi(httpClient);
MyEagerService.initialize(api) // 创建并注册单例
.doSomething(); // 使用实例
}
MyEagerService().doSomething(); // 使用单例实例
未来单例
处理依赖异步资源的单例可能有些棘手。不幸的是,在 Flutter/Dart 中,异步资源无处不在。
与 Singleton 库一起处理这种情况
class AppSettings {
static Future<AppSettings> loadAppSettings() {
// 从某个地方异步加载应用设置
}
}
class HttpClient {
final AppSettings appSettings;
HttpClient(this.appSettings);
}
使用 Singleton 库定义类型:
class MyFutureService {
/// 工厂方法自动复用相同的实例
factory MyFutureService() => Singleton<MyFutureService>().instance;
static Future<MyFutureService> createInstance() async {
final appSettings = await Singleton<AppSettings>().ensuredInstance();
final httpClient = HttpClient(appSettings);
return MyFutureService._(httpClient);
}
final HttpClient httpClient;
MyFutureService._(this.httpClient);
/// 执行某些操作
void doSomething() {}
}
注册未来单例。Singleton.register 了解 Future,它解析 Future 并将 Future 的值注册为单例。
void main() {
// 将 AppSettings 设置为未来单例
Singleton.register(AppSettings.loadAppSettings());
// 创建并注册 MyService 作为单例
Singleton.register(MyFutureService.createInstance());
runApp();
}
使用未来单例
未来单例可以像其他类型的单例一样使用,
MyFutureService().doSomething();
但如果单例是在未来解析之前被使用,将会抛出一个 StateError 说 “Singleton is being used before being resolved”。可以通过确保实例在检查点处执行实例创建来避免此错误:
await Singleton.ensureInstanceFor(MyFutureService);
可以同时检查多个类型:
await Singleton.ensureInstanceFor([MyFutureService, AppSettings]);
错误处理
如果未来的错误被抛出,该错误不会丢失,它会在调用 Singleton.ensureInstanceFor 或 Singleton.instance 时重新抛出。
支持单元测试
由于 Singleton 跨越测试边界,它们可能会导致意外的测试失败。通过 Singleton 库创建的 Singleton 可以通过仅在测试中可见的 API 清除。
setUp(() {
// 在设置环境之前重置单例注册表,以避免潜在的污染
Singleton.resetAllForTest();
Singleton.register(...);
});
tearDown(() {
Singleton.resetAllForTest(); // 重置单例注册表,避免单例污染
});
查看已注册的单例
有时你可能希望检查单例的状态以进行诊断。你可以通过以下方式实现:
Singleton.debugPrintAll();
或者只关心某些类型:
Singleton.debugPrintAll(MySingleton);
Singleton.debugPrintAll(Singleton<MySingleton>());
Singleton.debugPrintAll([MySingleton, AnotherSingleton]);
Singleton.debugPrintAll([Singleton<MySingleton>(), Singleton<AnotherSingleton>()]);
Singleton.debugPrintAll([Singleton<MySingleton>(), AnotherSingleton]);
删除单例
这应该是罕见的情况,但在某些极端情况下,如果你想摆脱你的单例。这是可能的:
Singleton<MySingleton>().deregister();
更多关于Flutter单例模式实现插件singleton的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter单例模式实现插件singleton的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,单例模式是一种常见的设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。使用单例模式可以避免重复创建对象,节省资源,并且可以在整个应用程序中共享状态。
在Flutter中实现单例模式通常有两种方式:
- 使用工厂构造函数
- 使用
Singleton插件
1. 使用工厂构造函数实现单例模式
class Singleton {
// 私有静态实例变量
static final Singleton _instance = Singleton._internal();
// 私有构造函数
Singleton._internal();
// 工厂构造函数,返回唯一的实例
factory Singleton() {
return _instance;
}
// 示例方法
void doSomething() {
print("Doing something...");
}
}
void main() {
// 获取单例实例
Singleton instance1 = Singleton();
Singleton instance2 = Singleton();
// 检查是否为同一个实例
print(identical(instance1, instance2)); // 输出: true
instance1.doSomething();
}
2. 使用Singleton插件实现单例模式
Singleton插件是一个第三方库,可以帮助你更简单地实现单例模式。你可以通过以下步骤使用它:
步骤1:添加依赖
在pubspec.yaml文件中添加singleton插件的依赖:
dependencies:
flutter:
sdk: flutter
singleton: ^2.0.0
然后运行flutter pub get来安装依赖。
步骤2:使用Singleton插件
import 'package:singleton/singleton.dart';
class MyService {
// 使用Singleton注解
[@Singleton](/user/Singleton)(
deprecated: false,
lazy: true,
)
static final MyService _instance = MyService._internal();
// 私有构造函数
MyService._internal();
// 获取单例实例
static MyService get instance => _instance;
// 示例方法
void doSomething() {
print("Doing something...");
}
}
void main() {
// 获取单例实例
MyService instance1 = MyService.instance;
MyService instance2 = MyService.instance;
// 检查是否为同一个实例
print(identical(instance1, instance2)); // 输出: true
instance1.doSomething();
}

