Flutter依赖注入插件dart_dependency_injection的使用
Flutter依赖注入插件dart_dependency_injection的使用
此库受ioc_container启发,感谢作者。
开始使用
首先,创建一个ServiceCollection
:
var collection = ServiceCollection();
接着,向ServiceCollection
中添加服务:
// 添加一个瞬态服务:
collection.add<TestService>((serviceProvider) => TestService());
// 添加一个单例服务:
collection.addSingleton<TestSingletonService>((serviceProvider) => TestSingletonService());
// 添加一个作用域单例服务:
collection.addScopedSingleton<TestScopedSingletonService>((serviceProvider) => TestScopedSingletonService());
然后,构建一个ServiceProvider
:
var provider = collection.build();
最后,从ServiceProvider
中获取服务:
var testService = provider.get<TestService>();
ServiceProvider
添加服务
创建一个ServiceCollection
:
var collection = ServiceCollection();
添加单例服务
collection.addSingleton<TestSingletonService>((serviceProvider) => TestSingletonService());
单例服务在整个当前作用域及其所有派生作用域中只有一个实例。
添加作用域单例服务
collection.addScopedSingleton<TestScopedSingletonService>((serviceProvider) => TestScopedSingletonService());
作用域单例服务在每次请求时都会获得不同的实例。但在相同的作用域内,该服务将始终返回相同的实例。
添加瞬态服务
collection.add<TestService>((serviceProvider) => TestService());
瞬态服务每次获取时都会创建新的实例。
构建ServiceProvider
var collection = ServiceCollection();
// ... 添加一些服务
var serviceProvider = collection.build();
构建完ServiceProvider
后,你将无法再添加服务,但可以构建作用域。
构建作用域的ServiceProvider
var collection = ServiceCollection();
// ... 添加一些服务
var parentProvider = collection.build();
// 构建一个作用域
var scopedServiceProvider = parentProvider.buildScoped(
builder: (collection) {
// ... 添加一些服务
},
);
作用域的ServiceProvider
会继承父级的所有服务,并且可以在其中添加额外的服务。
服务
获取服务实例
TestService testService = provider.get<TestService>();
// 或者
TestService testService = provider.getByType(TestService);
如果服务不存在,则会抛出异常。
或者
TestService? testService = provider.tryGet<TestService>();
// 或者
TestService? testService = provider.tryGetType(TestService);
如果服务不存在,则返回null。
服务作用域
对于单例服务,其作用域总是它被定义的那个作用域。
对于作用域单例服务,其作用域是它被创建的那个作用域。
对于瞬态服务,其作用域也是它被创建的那个作用域。
服务初始化
如果注入的服务实现了DependencyInjectionService
并覆盖了dependencyInjectionServiceInitialize
方法,那么该方法将在创建后立即执行。
编写初始化代码如下:
class TestService with DependencyInjectionService {
[@override](/user/override)
FutureOr dependencyInjectionServiceInitialize(){
print("运行在服务创建时");
}
}
dependencyInjectionServiceInitialize
方法可以是异步的,ServiceProvider
中有两个方法可以等待异步初始化:
/// 等待最近请求的服务完成初始化。必须在获取服务后立即调用。
FutureOr waitLatestServiceInitialize();
/// 等待所有正在初始化的服务完成。
FutureOr waitServicesInitialize();
在ServiceProvider构建时初始化
当添加服务时有一个参数initializeWhenServiceProviderBuilt
,如果设置为true
,则服务将在生成ServiceProvider
后立即创建并初始化。
一些代码如下:
var collection = ServiceCollection();
collection.add<TestService>((serviceProvider) => TestService(), initializeWhenServiceProviderBuilt: true);
var provider = collection.build();
// TestService 将被创建一次并立即初始化
ServiceObserver
ServiceObserver
是一个接口,可以通过实现它来观察服务的创建、初始化和销毁。
abstract class ServiceObserver<T> {
void onServiceCreated(T service);
void onServiceInitializeDone(T service);
void onServiceDispose(T service);
}
为每个服务添加观察者
var collection = ServiceCollection();
// ...添加一些服务
collection.add<ServiceObserver>((serviceProvider) => TestServiceObserver());
当服务创建时,会创建一个ServiceObserver
服务来观察这个服务。
为特定服务添加观察者
var collection = ServiceCollection();
// ...添加一些服务
collection.add<ServiceObserver<TestService>>((serviceProvider) => TestServiceObserver());
只有TestService
及其子类会被观察到。
DependencyInjectionService
DependencyInjectionService
是一个混合(mixin),为通过依赖注入创建的服务提供了一些魔法方法。
/// 获取一个服务。
T getService<T extends Object>();
/// 尝试获取一个服务。如果服务不存在则返回null。
T? tryGetService<T extends Object>();
/// 通过类型获取一个服务。
dynamic getServiceByType(Type type);
/// 尝试通过类型获取一个服务。如果服务不存在则返回null。
dynamic tryGetServiceByType(Type type);
/// 等待最近请求的服务完成初始化。必须在获取服务后立即调用。
FutureOr waitLatestServiceInitialize();
/// 等待所有正在初始化的服务完成。
FutureOr waitServicesInitialize();
/// 创建一个作用域
ServiceProvider buildScopedServiceProvider<T>({void Function(ServiceCollection)? builder, Object? scope});
使用这些方法就像在你的作用域中使用ServiceProvider
一样。
ServiceProvider的销毁
调用ServiceProvider
的dispose
方法。ServiceProvider
也会为其所有存活的服务和所有子作用域调用dispose
方法。
服务的销毁
任何服务都可以自行调用dispose
方法。销毁后,你将无法使用DependencyInjectionService
的任何方法。并且使用DependencyInjectionService
的buildScopedServiceProvider
方法创建的作用域也将被销毁。
服务的销毁通常会在以下情况下自动调用:
-
对于单例服务,在定义其作用域销毁时调用。
-
对于作用域单例服务,在作用域销毁时调用。
-
对于瞬态服务:
- 如果不再使用,可能会随时被垃圾回收器(GC)清除。
- 当被GC清除时,由其
buildScopedServiceProvider
方法创建的ServiceProvider
也会调用dispose
。 - 如果仍然存活,当
ServiceProvider
销毁它时也会调用dispose
。
示例代码
以下是一个完整的示例代码,展示了如何使用dart_dependency_injection
插件进行依赖注入。
import 'package:dart_dependency_injection/dart_dependency_injection.dart';
class TestService2 {}
class TestService3 {}
class TestService with DependencyInjectionService {
void log(String text) {
getService<TestService2>();
print(text);
}
}
class TestObserver extends ServiceObserver with DependencyInjectionService {
[@override](/user/override)
void onServiceCreated(service) {
getService<TestService>().log("${service.runtimeType} created");
}
[@override](/user/override)
void onServiceDispose(service) {}
[@override](/user/override)
void onServiceInitializeDone(service) {}
}
void main() async {
var serviceCollection = ServiceCollection();
serviceCollection
.addSingleton<TestService>((serviceProvider) => TestService());
serviceCollection
.addSingleton<TestService2>((serviceProvider) => TestService2());
serviceCollection.addSingleton<TestService3>(
(serviceProvider) => TestService3(),
initializeWhenServiceProviderBuilt: true);
serviceCollection.add<ServiceObserver>((serviceProvider) => TestObserver());
serviceCollection.build();
}
更多关于Flutter依赖注入插件dart_dependency_injection的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter依赖注入插件dart_dependency_injection的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
dart_dependency_injection
是一个用于 Flutter 应用的依赖注入(Dependency Injection, DI)插件。它允许你在应用中更轻松地管理依赖关系,使得代码更具可测试性和可维护性。以下是如何使用 dart_dependency_injection
插件的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 dart_dependency_injection
依赖:
dependencies:
dart_dependency_injection: ^1.0.0
然后运行 flutter pub get
来安装依赖。
2. 创建依赖注入容器
在你的应用中,你可以创建一个依赖注入容器来管理所有的依赖关系。
import 'package:dart_dependency_injection/dart_dependency_injection.dart';
final container = DependencyContainer();
3. 注册依赖
你可以使用 register
方法来注册依赖。提供依赖的类型和一个工厂函数来创建该依赖的实例。
abstract class Service {
void doSomething();
}
class ServiceImpl implements Service {
@override
void doSomething() {
print('Doing something...');
}
}
container.register<Service>((_) => ServiceImpl());
4. 解析依赖
使用 resolve
方法来获取已注册的依赖实例。
final service = container.resolve<Service>();
service.doSomething();
5. 单例模式
如果你想将依赖注册为单例,可以使用 registerSingleton
方法。
container.registerSingleton<Service>((_) => ServiceImpl());
这样,每次调用 resolve<Service>()
时,都会返回同一个 ServiceImpl
实例。
6. 依赖注入
你可以在需要的地方通过构造函数注入依赖。
class MyBloc {
final Service service;
MyBloc(this.service);
void performAction() {
service.doSomething();
}
}
container.register<MyBloc>((c) => MyBloc(c.resolve<Service>()));
7. 使用依赖注入
在你的应用中使用依赖注入容器来创建对象。
void main() {
final bloc = container.resolve<MyBloc>();
bloc.performAction();
}
8. 依赖注入的高级用法
你可以使用命名依赖、条件依赖等高级特性来满足更复杂的场景。
container.register<Service>(
(_) => ServiceImpl(),
name: 'serviceA',
);
container.register<Service>(
(_) => AnotherServiceImpl(),
name: 'serviceB',
);
final serviceA = container.resolve<Service>(name: 'serviceA');
final serviceB = container.resolve<Service>(name: 'serviceB');
9. 清理容器
你可以在应用的生命周期结束时清理容器,释放资源。
container.dispose();