Flutter自动注入依赖插件auto_inject的使用

Flutter自动注入依赖插件auto_inject的使用

Auto Inject

auto_inject 是一个用于 Flutter 应用程序的代码生成库,用于通过 GetIt 自动注入依赖项,从而减少样板代码。我的目标不是支持 GetIt 提供的所有功能,而是使最常用的功能更加简洁,并提供一些我个人觉得有用的额外功能。

安装与配置

步骤1:添加所需的依赖项

pubspec.yaml 文件中添加以下依赖项:

dependencies:
  # GetIt本身
  get_it: any
  
  # 注解库
  auto_inject: any

dev_dependencies:
  # 构建运行器以执行代码生成器
  build_runner: any
  
  # 代码生成器
  auto_inject_dev: any

步骤2:启用代码生成器并指定入口文件

build.yaml 文件中添加以下内容,以启用代码生成器并将它指向一个入口文件(例如 lib/main.dart):

targets:
  $default:
    builders:
      auto_inject_dev|auto_inject_builder:
        enabled: true
        generate_for: 
          - lib/main.dart 

步骤3:调用生成的 initAutoInject 方法来配置 GetIt 实例

在你的应用程序的主方法中,调用生成的 initAutoInject 方法来配置 GetIt 实例。例如:

import 'file.auto.dart';

void main() {
    final instance = GetIt.instance;
    final environment = 'dev';

    // 调用init方法来配置GetIt实例 
    initAutoInject(instance, environment);

    // 现在实例已经准备好被使用
    final obj = instance<SomeClass>();
}

功能特性

基本注入

依赖项可以通过三种方式注册:

  • 可注入(注解为 @Injectable()):每次请求该类的新实例时,都会创建一个新的实例。
  • 单例(注解为 [@Singleton](/user/Singleton)()):当调用初始化方法时,类的实例会被创建,并且每次请求该类的实例时,都会提供相同的实例。
  • 懒加载单例(注解为 [@Singleton](/user/Singleton)(lazy: true)):类似于普通单例,但实例会在第一次请求该类的实例时才创建。

每个应由 GetIt 实例注册的类都需要使用这两种注解之一。依赖项可以像这样自动注入到另一个类的构造函数中:

[@Singleton](/user/Singleton)(env: 'env1')
class A {}

[@Singleton](/user/Singleton)(env: 'env1')
class B { 
  final A a;
  
  B(this.a)
}

或者也可以使用对 GetIt 实例的引用手动检索:

final b = GetIt.instance<B>();

环境

依赖项可以在一个或多个环境中注册。当调用初始化方法时,只会注册指定环境中的类。这在类在不同环境中具有不同实现时非常有用。例如:

class Flower { }

@Injectable(as: Flower, env: ['yellow'])
class YellowFlower implements Flower { }

@Injectable(as: Flower, env: ['red'])
class RedFlower implements Flower { }

@Injectable(env: ['yellow', 'red'])
class FlowerPot {
  final Flower flower;

  FlowerPot(this.flower);
}

如果在一个黄色环境中请求 FlowerPot 的实例,则会传递一个 YellowFlower 到构造函数中;而在红色环境中,则会传递一个 RedFlower

模块

如果无法给应该注入的类添加注解,则可以创建模块。这可能是因为该类是由第三方依赖项提供的。模块是带有 @module 注解的抽象类。模块的方法或属性可以注解,其返回类型将被注册到 GetIt 实例中。还可以在模块的方法中自动注入其他依赖项。例如:

@module
abstract class Module {
  // 提供依赖A
  @Injectable(env: ['env1'])
  A get a => A();
  
  // 提供依赖B,并且会自动注入A的实例
  @Injectable(env: ['env1'])
  B b(A a) => B(a);
}

也可以将多个类注册到一组。如果请求一组,则会提供该组中每个依赖项的实例。注册到组中的每个类还必须实现该组类型。例如:

class G { }

@Injectable(env: ['env1'], group: [G])
class A implements G { }

[@Singleton](/user/Singleton)(env: ['env1'], group: [G])
class B implements G { }

可以通过在构造函数参数或模块函数参数上注解 @group 来自动注入该组的实例。组参数必须是 ListIterable

@Injectable(env: ['env1'])
class C {
  final List<G> g;
  
  C(@group this.g);
}

如果组为空,则会注入空列表。

辅助注入

有时需要手动提供值或依赖项。因此,可以在构造函数参数或模块函数参数上注解 @assisted。但是,辅助注入只能与 @Injectable 一起使用,并且不能自动将这些依赖项注入其他依赖项中。对于每个辅助依赖项,将在 AutoFactory 上生成一个函数。可以使用该工厂实例来创建辅助依赖项的实例。例如:

@Injectable(env: ['env1'])
class A { 
  final String info;
  
  A(@assisted this.info)
}

@Injectable(env: ['env1'])
class B {
  final A a;
  
  B(AutoFactory factory) : a = factory.getA('Additional information');
}

外部模块

为了使模块更灵活,可以创建外部模块。外部模块是带有 [@externModule](/user/externModule) 注解的抽象类。与普通模块不同,它们不提供所依赖项的实现。可以在初始化方法中传入提供这些实现的实例。这在测试期间注入模拟对象到测试环境中时非常有用。例如:

[@Singleton](/user/Singleton)(env: ['prod'])
class A { }

[@externModule](/user/externModule)
abstract class Module {
  [@Singleton](/user/Singleton)(env: ['test'])
  A get a;
}

class TestModule implements Module {
  [@override](/user/override)
  A get a => MockA();
}

void main() {
  initAutoInject(GetIt.instance, 'test', externModules: [TestModule()]);
}

更多关于Flutter自动注入依赖插件auto_inject的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


当然,auto_inject 是一个用于 Flutter 的依赖注入插件,它可以简化依赖注入的过程,通过注解和代码生成工具来自动注入依赖。以下是如何在 Flutter 项目中使用 auto_inject 的一个简单示例。

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 auto_inject 和其依赖项 build_runner

dependencies:
  flutter:
    sdk: flutter
  auto_inject: ^x.y.z  # 请替换为最新版本号

dev_dependencies:
  build_runner: ^x.y.z  # 请替换为最新版本号

然后运行 flutter pub get 来获取依赖。

2. 配置 build.yaml

在项目的根目录下创建或编辑 build.yaml 文件,添加以下内容以配置代码生成:

targets:
  $default:
    builders:
      auto_inject:auto_inject:
        enabled: true

3. 创建依赖接口和实现类

假设我们有一个简单的服务接口 MyService 和它的实现类 MyServiceImpl

// my_service.dart
abstract class MyService {
  void doSomething();
}

// my_service_impl.dart
import 'package:auto_inject/auto_inject.dart';

@Injectable()
class MyServiceImpl implements MyService {
  @override
  void doSomething() {
    print('Doing something in MyServiceImpl');
  }
}

4. 使用依赖注入

接下来,我们在需要使用 MyService 的地方进行依赖注入。首先,我们需要一个容器来管理依赖:

// main.dart
import 'package:flutter/material.dart';
import 'package:auto_inject/auto_inject.dart';
import 'my_service.dart';
import 'my_service_impl.dart';

void main() {
  // 初始化依赖注入容器
  setupInjector();

  runApp(MyApp());
}

@Injector([MyServiceImpl])
void setupInjector() {
  // 这里会自动注册所有被 @Injectable 注解的类
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  // 使用依赖注入获取 MyService 的实例
  final MyService myService = getIt<MyService>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Auto Inject Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            myService.doSomething();
          },
          child: Text('Press Me'),
        ),
      ),
    );
  }
}

5. 生成代码

在终端中运行以下命令来生成依赖注入所需的代码:

flutter pub run build_runner build

6. 运行应用

现在,你可以运行你的 Flutter 应用,当你点击按钮时,应该会看到控制台输出 “Doing something in MyServiceImpl”。

这个示例展示了如何使用 auto_inject 插件在 Flutter 项目中自动注入依赖。请注意,实际应用中可能需要更复杂的依赖关系和配置,但基本的用法是类似的。

回到顶部