Flutter依赖注入与代码生成插件zef_di_core_generator的使用

Flutter依赖注入与代码生成插件zef_di_core_generator的使用

zef_di_core_generator

一个用于生成代码的插件,它基于zef_di_core库,可以自动根据项目中的自定义注解生成服务注册代码。

特性

  • 自动服务注册:基于自定义注解,自动生成服务注册代码。
  • 无缝集成:与zef_di_core库完美配合,提升开发体验。
  • 提高开发效率:减少手动编码和潜在的人为错误,加快开发速度。

开始使用

以下是将此插件集成到项目的步骤:

安装

  1. pubspec.yaml文件的dependencies部分添加zef_di_core

    dependencies:
      zef_di_core: latest_version
    
  2. pubspec.yaml文件的dev_dependencies部分添加zef_di_core_generator

    dev_dependencies:
      zef_di_core_generator: latest_version
    
  3. 运行以下命令以安装包:

    dart run pub get
    

    或者使用flutter pub get


使用方法

1. 注解服务

在需要注册的服务类上添加zef_di_core的注解。

2. 运行构建器生成代码

运行以下命令以生成服务注册代码:

dart run build_runner build

之后,您可以在应用启动时调用registerDependencies函数来注册依赖项:

void main(List<String> arguments) {
  // 创建 ServiceLocator 实例
  ServiceLocatorBuilder().build();

  // 调用生成的依赖项注册函数
  registerDependencies();

  ... 其他代码
}

示例

单例模式(Singleton)

以下是一个简单的示例,展示了如何注册SingletonService

注解服务类:

import 'package:zef_di_core/zef_di_core.dart';

@RegisterSingleton()
class SingletonService {
  void doSomething() {
    print("Doing something...");
  }
}

生成的代码:

运行构建器后,会在zef.di.g.dart文件中生成以下代码:

void registerDependencies() {
  ServiceLocator.I.registerInstance<SingletonService>(
    SingletonService(),
    interfaces: null,
    name: null,
    key: null,
    environment: null,
  );
}

瞬态模式(Transient)

瞬态模式表示每次解析该类时都会实例化一次。

注解服务类:

import 'package:zef_di_core/zef_di_core.dart';

@RegisterTransient()
class TransientService {
  void doSomething() {
    print("Doing something...");
  }
}

生成的代码:

运行构建器后,会在zef.di.g.dart文件中生成以下代码:

ServiceLocator.I.registerTransient<TransientService>(
    (args) => TransientService(),
    interfaces: null,
    name: null,
    key: null,
    environment: null,
);

工厂方法(Factory Method)

如果需要手动控制类的构造方式,可以使用@RegisterFactoryMethod注解。

注解工厂方法:

@RegisterFactoryMethod()
static FactoryMethodService create() {
  return FactoryMethodService();
}

参数传递(Passing Parameters)

代码生成器还可以处理依赖项解析时的参数传递。

注解服务类:

import 'package:zef_di_core/zef_di_core.dart';

@RegisterTransient()
class TransientService {
  final AnyOtherService _anyOtherService;
  final double _anyValue;

  TransientService(
    // 自动尝试从 ServiceLocator 中解析此参数
    this._anyOtherService, 

    // 告诉生成器此参数通过 `args` 传递
    @Passed() required double anyValue,
  ) : _anyValue = anyValue;
}

懒加载注册(Lazy Registration)

懒加载允许在服务真正被需要时才进行实例化,从而加快应用启动速度。

注解服务类:

import 'package:zef_di_core/zef_di_core.dart';

@RegisterLazy()
class LazyService {
  void doSomething() {
    print("Doing something lazily...");
  }
}

生成的代码:

运行构建器后,会在zef.di.g.dart文件中生成以下代码:

void registerDependencies() {
  ServiceLocator.I.registerLazy<LazyService>(
    Lazy<LazyService>(factory: () => LazyService()),
    interfaces: null,
    name: null,
    key: null,
    environment: null,
  );
}

外部依赖注册

对于来自其他包的类,无法直接注解,因此需要定义一个模块(Module)。

定义模块:

@DependencyModule()
abstract class ExternalClassesModule {
  // 单例需要通过 getter 注册
  @RegisterSingleton()
  ExternalClassA get externalClassA;

  // 瞬态注册为方法
  @RegisterTransient()
  ExternalClassB externalClassB(ExternalClassA externalClassA) =>
      ExternalClassB(externalClassA);

  // 懒加载也是方法
  @RegisterLazy()
  ExternalClassC externalClassC(
    ExternalClassA externalClassA,
    ExternalClassB externalClassB,
  ) =>
      ExternalClassC(externalClassA, externalClassB);
}

示例代码

以下是从官方示例中提取的完整代码:

import 'package:example/test_files/lazy_services.dart';
import 'package:example/test_files/transient_services.dart';
import 'package:example/zef.di.register.g.dart';
import 'package:zef_di_core/zef_di_core.dart';

import 'test_files/singleton_services.dart';

void main(List<String> arguments) async {
  ServiceLocatorBuilder().build();

  await registerDependencies();

  await resolveSingletons();
  await resolveTransients();
  await resolveLazies();
}

Future<void> resolveSingletons() async {
  final singletonNoDependencies =
      await ServiceLocator.instance.resolve<SingletonNoDependencies>();
  singletonNoDependencies.doSomething();

  final singletonWithFactory =
      await ServiceLocator.instance.resolve<SingletonWithFactory>();
  singletonWithFactory.doSomething();

  final singletonWithDependencies =
      await ServiceLocator.instance.resolve<SingletonWithDependencies>();
  singletonWithDependencies.doSomething();

  final singletonWithFactoryWithDependencies = await ServiceLocator.instance
      .resolve<SingletonWithFactoryWithDependencies>();
  singletonWithFactoryWithDependencies.doSomething();
}

Future<void> resolveTransients() async {
  final transientNoDependencies =
      await ServiceLocator.instance.resolve<TransientNoDependencies>();
  transientNoDependencies.doSomething();

  final transientWithFactory =
      await ServiceLocator.instance.resolve<TransientWithFactory>();
  transientWithFactory.doSomething();

  final transientWithDependencies =
      await ServiceLocator.instance.resolve<TransientWithDependencies>();
  transientWithDependencies.doSomething();

  final transientWithFactoryWithDependencies = await ServiceLocator.instance
      .resolve<TransientWithFactoryWithDependencies>();
  transientWithFactoryWithDependencies.doSomething();

  final transientWithArgs =
      await ServiceLocator.instance.resolve<TransientWithArgs>(args: {
    'someValue': 5.0,
  });
  transientWithArgs.doSomething();

  final transientWithFactoryWithArgs = await ServiceLocator.instance
      .resolve<TransientWithFactoryWithArgs>(args: {
    'someValue': 5.0,
  });
  transientWithFactoryWithArgs.doSomething();

  final transientWithFactoryWithDependencyWithArgs = await ServiceLocator
      .instance
      .resolve<TransientWithFactoryWithDependencyWithArgs>(args: {
    'someValue': 5.0,
  });
  transientWithFactoryWithDependencyWithArgs.doSomething();

  final transientWithAsyncFactory =
      await ServiceLocator.instance.resolve<TransientWithAsyncFactory>();
  transientWithAsyncFactory.doSomething();
}

Future<void> resolveLazies() async {
  final lazyNoDependencies =
      await ServiceLocator.instance.resolve<LazyNoDependencies>();
  lazyNoDependencies.doSomething();

  final lazyWithFactoryNoDependencies =
      await ServiceLocator.instance.resolve<LazyWithFactoryNoDependencies>();
  lazyWithFactoryNoDependencies.doSomething();

  final lazyWithDependencies =
      await ServiceLocator.instance.resolve<LazyWithDependencies>();
  lazyWithDependencies.doSomething();

  final lazyWithFactoryWithDependencies =
      await ServiceLocator.instance.resolve<LazyWithFactoryWithDependencies>();
  lazyWithFactoryWithDependencies.doSomething();
}

更多关于Flutter依赖注入与代码生成插件zef_di_core_generator的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter依赖注入与代码生成插件zef_di_core_generator的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,依赖注入(Dependency Injection, DI)是一种设计模式,用于管理对象之间的依赖关系。通过依赖注入,你可以将对象的创建和依赖关系的管理从具体的业务逻辑中解耦出来,从而提高代码的可维护性和可测试性。

zef_di_core_generator 是一个用于生成依赖注入代码的插件,它可以帮助你自动化生成依赖注入的代码。下面是如何在Flutter项目中使用 zef_di_core_generator 的步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 zef_di_corezef_di_core_generator 的依赖。

dependencies:
  zef_di_core: ^1.0.0

dev_dependencies:
  zef_di_core_generator: ^1.0.0
  build_runner: ^2.1.0

2. 创建一个服务类

假设你有一个服务类 MyService,你希望通过依赖注入来管理它。

class MyService {
  void doSomething() {
    print('Doing something!');
  }
}

3. 使用 @Injectable 注解

为了让 zef_di_core_generator 生成依赖注入代码,你需要在服务类上使用 @Injectable 注解。

import 'package:zef_di_core/zef_di_core.dart';

@Injectable()
class MyService {
  void doSomething() {
    print('Doing something!');
  }
}

4. 生成依赖注入代码

运行以下命令来生成依赖注入代码:

flutter pub run build_runner build

这将会生成一个名为 *.inject.dart 的文件,其中包含了依赖注入的代码。

5. 注册依赖

在生成的代码中,你需要在应用程序的入口处注册依赖。

import 'package:zef_di_core/zef_di_core.dart';
import 'my_service.dart';
import 'my_service.inject.dart';

void main() {
  // 注册依赖
  ServiceLocator.I.registerSingleton<MyService>(MyService());

  // 运行应用程序
  runApp(MyApp());
}

6. 使用依赖注入

现在你可以在应用程序的其他部分通过依赖注入来获取 MyService 的实例。

import 'package:flutter/material.dart';
import 'package:zef_di_core/zef_di_core.dart';
import 'my_service.dart';

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    // 获取 MyService 实例
    final myService = ServiceLocator.I.resolve<MyService>();

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter DI Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              myService.doSomething();
            },
            child: Text('Do Something'),
          ),
        ),
      ),
    );
  }
}
回到顶部