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
来自动注入该组的实例。组参数必须是 List
或 Iterable
。
@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
更多关于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 项目中自动注入依赖。请注意,实际应用中可能需要更复杂的依赖关系和配置,但基本的用法是类似的。