Flutter依赖注入插件zef_di_core的使用
Flutter依赖注入插件zef_di_core的使用
zef_di_core
是一个用于依赖注入的Dart库,它提供了一组抽象接口和默认实现。这个项目是 zef_di_abstractions
和 zef_di_inglue
的延续。如果你还在使用这些库,建议升级到这个新的版本。
特性
- 框架无关:设计为一个灵活的包装器,可以与任何依赖注入(DI)框架一起使用,提供统一的服务注册和解析接口。
- 多服务解析:支持解析注册在相同接口下的多个服务,增强了复杂应用中的服务检索灵活性。
- 自定义适配器集成:允许用户通过编写自定义适配器来集成任何外部DI框架,确保兼容性并根据项目需求扩展功能。
- 无限参数:与其他DI框架不同,我们提供了在解析依赖时传递任意数量参数的能力。
- 代码生成:自动化的依赖注册和解析。
定义
Singleton
单例是存储在内存中并每次解析依赖时重用的实例。这使得它们非常快,但占用大量内存。请注意,当你手动销毁对象(或通过外部包销毁)后,引用仍然存在于DI框架中,但会抛出异常。
Transient
瞬态注册就像注册一个每次请求对象时都会调用的函数。这种方式内存使用量最小,因为没有缓存实例,但在每次请求时都会实例化对象,可能会导致性能问题。
Lazy
懒加载是单例和瞬态的结合。你将注册一个工厂,该工厂将在首次解析类型时调用,然后实例将存储在内存中。这样,你总是可以获取相同的实例。
入门
初始化和使用
我们喜欢“建造者”模式,所以这是初始化服务定位器的方法。在你的 main()
函数中,像这样调用它:
void main() {
ServiceLocatorBuilder()
.build();
// 应用逻辑
}
你可以通过 ServiceLocator.instance
或简写 ServiceLocator.I
访问它。
单例
简单注册
要注册一个单例,直接传递你想要注册的对象实例:
ServiceLocator.I.registerSingleton(Dolphin());
要解析该实例,调用 resolve()
方法:
final Dolphin dolphin = ServiceLocator.I.resolve<Dolphin>();
注意
你可以多次注册相同的实例,如果已经在 ServiceLocatorConfig
中设置了此选项。默认情况下是开启的。resolve()
方法将返回第一个注册的实例,但你可以通过以下方式获取最后一个注册的实例:
final Dolphin dolphin = ServiceLocator.I.resolve<Dolphin>(resolveFirst: false);
相同的原理适用于以下注册选项。
使用工厂注册
你也可以使用工厂注册单例:
ServiceLocator.I.registerSingletonFactory<MyService>(
(args) => MyService(),
);
这样你就可以更灵活地控制实例创建。注意,工厂只会被调用一次,并且是在注册后立即调用的。
命名注册
你可以为注册传递一个名称:
ServiceLocator.I.registerSingleton(Dolphin(), name: 'One');
ServiceLocator.I.registerSingleton(Dolphin(), name: 'Two');
这样你可以轻松解析不同的实例:
final Dolphin dolphin = ServiceLocator.I.resolve<Dolphin>(name: 'one'); // 返回名为 `one` 的实例
final Dolphin dolphin = ServiceLocator.I.resolve<Dolphin>(name: 'two'); // 返回名为 `two` 的实例
键值注册
键值注册与命名注册类似,但使用不同的属性。
环境注册
环境注册也与命名注册类似,但用于定义不同环境(如 “dev”, “test”, “prod”)下的实例。
瞬态注册
简单注册
ServiceLocator.I.registerTransient<MyService>(
(args) => MyService(),
);
解析时,你像处理单例一样操作:
final MyService myService = ServiceLocator.I.resolve<MyService>();
带参数解析
瞬态工厂的一个特性是你可以在解析实例时传递参数。首先,你需要告诉框架如何解析工厂:
ServiceLocator.I.registerTransient<UserService>(
(Map<String, dynamic> args) => UserService(
id: args['theUserId'] as UserId, // 这是参数提供的方式
username: args['theUsername'], // 你不需要指定类型
password: args['thePassword'] as String, // 但必须传递所有所需参数
),
);
args
参数是一个映射表,你在尝试解析工厂时传递的参数:
final UserService userService = ServiceLocator.I.resolve<UserService>(
args: {
'theUserId': UserId('1'),
'theUsername': 'HansZimmer123',
'thePassword': 'blafoo1!',
},
);
如果你没有传递必需的参数,将会抛出 TypeError
。
懒加载注册
ServiceLocator.I.registerLazy<MyLazyService>(
Lazy<MyLazyService>(() => MyLazyService()),
);
解析懒加载注册的服务时,使用相同的解析方法:
final MyLazyService myLazyService = ServiceLocator.I.resolve<MyLazyService>();
自定义适配器的实现
这个包附带了一个内置适配器,应该能满足大部分需求,但你仍然可以开发自己的适配器以获得完全控制。这是一个概念性的示例来指导你:
class MyDIAdapter extends ServiceLocatorAdapter {
// 使用你选择的DI框架实现适配器方法
}
更多关于Flutter依赖注入插件zef_di_core的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter依赖注入插件zef_di_core的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用zef_di_core
插件进行依赖注入的示例代码。zef_di_core
是一个用于依赖注入的插件,它可以帮助你管理应用程序中的依赖关系,使代码更加模块化和易于测试。
1. 添加依赖
首先,你需要在pubspec.yaml
文件中添加zef_di_core
依赖:
dependencies:
flutter:
sdk: flutter
zef_di_core: ^最新版本号
确保你替换了最新版本号
为当前可用的最新版本。
2. 配置依赖注入容器
在你的Flutter项目中,你需要创建一个依赖注入容器。通常,你会在应用程序的入口点(如main.dart
)进行此操作。
import 'package:flutter/material.dart';
import 'package:zef_di_core/zef_di_core.dart';
// 假设你有两个服务类
class MyService {
void doSomething() {
print("Service is doing something!");
}
}
class AnotherService {
final MyService myService;
AnotherService(this.myService);
void doAnotherThing() {
myService.doSomething();
print("Another service is doing another thing!");
}
}
void main() {
// 创建依赖注入容器
final diContainer = DiContainer();
// 注册服务
diContainer.register<MyService>(() => MyService());
diContainer.register<AnotherService>(
() => AnotherService(diContainer.resolve<MyService>())
);
runApp(
DiWidget(
container: diContainer,
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
3. 在Widget中使用依赖注入
现在,你可以在Widget中通过依赖注入容器获取服务实例。这里我们假设在HomeScreen
中使用AnotherService
。
import 'package:flutter/material.dart';
import 'package:zef_di_core/zef_di_core.dart';
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 使用DiContainer.of方法获取依赖注入容器
final diContainer = DiContainer.of(context);
final anotherService = diContainer.resolve<AnotherService>();
return Scaffold(
appBar: AppBar(
title: Text('Home Screen'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
anotherService.doAnotherThing();
},
child: Text('Press me'),
),
),
);
}
}
完整代码
import 'package:flutter/material.dart';
import 'package:zef_di_core/zef_di_core.dart';
// 服务类
class MyService {
void doSomething() {
print("Service is doing something!");
}
}
class AnotherService {
final MyService myService;
AnotherService(this.myService);
void doAnotherThing() {
myService.doSomething();
print("Another service is doing another thing!");
}
}
void main() {
final diContainer = DiContainer();
diContainer.register<MyService>(() => MyService());
diContainer.register<AnotherService>(
() => AnotherService(diContainer.resolve<MyService>())
);
runApp(
DiWidget(
container: diContainer,
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final diContainer = DiContainer.of(context);
final anotherService = diContainer.resolve<AnotherService>();
return Scaffold(
appBar: AppBar(
title: Text('Home Screen'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
anotherService.doAnotherThing();
},
child: Text('Press me'),
),
),
);
}
}
这个示例展示了如何使用zef_di_core
插件在Flutter项目中进行依赖注入。通过这种方法,你可以轻松管理应用程序中的依赖关系,使代码更加模块化和易于维护。