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&lt;T&gt; {
  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&lt;TestService&gt;&gt;((serviceProvider) =&gt; TestServiceObserver());

只有TestService及其子类会被观察到。

DependencyInjectionService

DependencyInjectionService是一个混合(mixin),为通过依赖注入创建的服务提供了一些魔法方法。

/// 获取一个服务。
T getService&lt;T extends Object&gt;();

/// 尝试获取一个服务。如果服务不存在则返回null。
T? tryGetService&lt;T extends Object&gt;();

/// 通过类型获取一个服务。
dynamic getServiceByType(Type type);

/// 尝试通过类型获取一个服务。如果服务不存在则返回null。
dynamic tryGetServiceByType(Type type);

/// 等待最近请求的服务完成初始化。必须在获取服务后立即调用。
FutureOr waitLatestServiceInitialize();

/// 等待所有正在初始化的服务完成。
FutureOr waitServicesInitialize();

/// 创建一个作用域
ServiceProvider buildScopedServiceProvider&lt;T&gt;({void Function(ServiceCollection)? builder, Object? scope});

使用这些方法就像在你的作用域中使用ServiceProvider一样。

ServiceProvider的销毁

调用ServiceProviderdispose方法。ServiceProvider也会为其所有存活的服务和所有子作用域调用dispose方法。

服务的销毁

任何服务都可以自行调用dispose方法。销毁后,你将无法使用DependencyInjectionService的任何方法。并且使用DependencyInjectionServicebuildScopedServiceProvider方法创建的作用域也将被销毁。

服务的销毁通常会在以下情况下自动调用:

  • 对于单例服务,在定义其作用域销毁时调用。

  • 对于作用域单例服务,在作用域销毁时调用。

  • 对于瞬态服务:

    • 如果不再使用,可能会随时被垃圾回收器(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

1 回复

更多关于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();
回到顶部