Flutter依赖注入插件injectable_micropackages的使用

Flutter依赖注入插件injectable_micropackages的使用

Injectable 是一个用于 get_it 的便捷代码生成器。它受到 Angular DI、Guice DI 和 inject.dart 的启发。

目录

安装

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

dependencies:
  # 添加 injectable 到你的依赖项
  injectable:
  # 添加 get_it
  get_It:

dev_dependencies:
  # 添加生成器到你的 dev_dependencies
  injectable_generator:
  # 当然需要 build_runner 来运行生成器
  build_runner:

设置

  1. 创建一个新的 Dart 文件,并定义一个全局变量来存储你的 GetIt 实例。
  2. 定义一个顶级函数(我们称之为 configureDependencies),并用 @injectableInit 注解它。
  3. 调用生成的函数 $initGetIt() 或自定义初始化名称,并将 getIt 实例传递进去。
  4. main 函数中调用 configureDependencies(),并在运行应用之前执行。
final getIt = GetIt.instance;

@InjectableInit(
  initializerName: r'$initGetIt', // 默认值
  preferRelativeImports: true, // 默认值
  asExtension: false, // 默认值
)
void configureDependencies() => $initGetIt(getIt);

// 如果你想告诉 injectable 处理特定目录内的文件,可以使用 generateForDir 属性
// 例如,只处理 test 文件夹中的文件
@InjectableInit(generateForDir: ['test'])
void configureDependencies() => $initGetIt(getIt);

void main() {
  configureDependencies();
  runApp(MyApp());
}

注册工厂

所有你需要做的就是使用 [@injectable](/user/injectable) 注解你的可注入类,并让生成器完成工作。

[@injectable](/user/injectable)
class ServiceA {}

[@injectable](/user/injectable)
class ServiceB {
  ServiceB(ServiceA serviceA);
}

运行生成器

使用 [watch] 标志来监视文件系统中的更改,并根据需要重新构建。

flutter packages pub run build_runner watch

如果只想运行一次生成器并退出,则使用:

flutter packages pub run build_runner build

生成文件内部

Injectable 将为你生成所需的注册函数。

final getIt = GetIt.instance;

void $initGetIt(GetIt getIt, {String environment, EnvironmentFilter environmentFilter}) {
  final gh = GetItHelper(getIt, environment);
  gh.factory<ServiceA>(() => ServiceA());
  gh.factory<ServiceB>(ServiceA(getIt<ServiceA>()));
}

注册单例

使用 [@singleton](/user/singleton)@lazySingleton 注解你的单例类。

[@singleton](/user/singleton) // 或者 @lazySingleton
class ApiProvider {}

注册异步注入对象

如果实例化需要异步操作,你将需要一个静态初始化方法,因为构造函数不能是异步的。

class ApiClient {
  static Future<ApiClient> create(Deps ...) async {
    ....
    return apiClient;
  }
}

现在只需使用 [@injectable](/user/injectable) 注解你的类,并使用 [@factoryMethod](/user/factoryMethod) 注解来告诉 injectable 使用静态初始化方法作为工厂方法。

[@injectable](/user/injectable) // 或者 lazy/singleton
class ApiClient {
  [@factoryMethod](/user/factoryMethod)
  static Future<ApiClient> create(Deps ...) async {
    ....
    return apiClient;
  }
}

生成的代码:

factoryAsync<ApiClient>(() => ApiClient.create());

传递参数给工厂

如果你的工作涉及一个你可以控制的类,只需使用 @factoryParam 注解你的可变构造函数参数即可。最多可以有两个参数!

[@injectable](/user/injectable)
class BackendService {
  BackendService(@factoryParam String url);
}

生成的代码:

factoryParam<BackendService, String, dynamic>(
  (url, _) => BackendService(url),
);

绑定抽象类到实现

使用 [@Injectable](/user/Injectable)(as: ..) 注解内的 as 属性来传递由注册依赖项实现的抽象类型。

[@Injectable](/user/Injectable)(as: Service)
class ServiceImpl implements Service {}

// 或者
@Singleton(as: Service) 
class ServiceImpl implements Service {}

// 或者
@LazySingleton(as: Service) 
class ServiceImpl implements Service {}

生成的代码:

factory<Service>(() => ServiceImpl())

注册在不同环境下的对象

通过使用 @Environment('name') 注解来注册不同环境下的不同依赖项。

@Environment("dev")
[@injectable](/user/injectable)
class ServiceA {}

或者,你可以通过 env 属性来分配环境名到你的依赖项。

[@Injectable](/user/Injectable)(as: Service, env: [Environment.dev, Environment.test])
class RealServiceImpl implements Service {}
``

### 使用命名工厂和静态创建函数

默认情况下,injectable 将使用默认构造函数来构建你的依赖项,但你可以通过 `[@factoryMethod](/user/factoryMethod)` 注解来告诉 injectable 使用命名构造函数或静态创建函数。

```dart
[@injectable](/user/injectable)
class MyRepository {
  [@factoryMethod](/user/factoryMethod)
  MyRepository.from(Service s);
}

生成的代码:

factory<MyRepository>(MyRepository.from(getIt<Service>()))

注册第三方类型

为了注册第三方类型,创建一个抽象类并使用 [@module](/user/module) 注解,然后添加你的第三方类型作为属性访问器或方法。

[@module](/user/module)
abstract class RegisterModule {
  [@singleton](/user/singleton)
  ThirdPartyType get thirdPartyType;

  [@prod](/user/prod)
  [@Injectable](/user/Injectable)(as: ThirdPartyAbstract)
  ThirdPartyImpl get thirdPartyType;
}

自动注册

通过使用约定优于配置的方式,可以在微包架构中自动注册你的可注入类。

targets:
  $default:
    builders:
      injectable_generator:injectable_builder:
        options:
          auto_register: true
          class_name_pattern: "Service$|Repository$|Bloc$"
          file_name_pattern: "_service$|_repository$|_bloc$"

示例

import 'package:injectable/injectable_annotations.dart';

abstract class Service {}

[@named](/user/named)
[@prod](/user/prod)
[@Injectable](/user/Injectable)(as: Service)
class ServiceImpl1 extends Service {}

[@Injectable](/user/Injectable)(as: Service, env: [Environment.dev])
class ServiceImpl2 implements Service {}

[@injectable](/user/injectable)
class MyRepository {
  MyRepository(@Named.from(ServiceImpl1) Service service);
}

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

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用injectable_micropackages插件来实现依赖注入的代码示例。injectable_micropackages是一个流行的Flutter依赖注入库,它基于get_it包,但提供了更多的功能和简化配置。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加injectableget_it的依赖:

dependencies:
  flutter:
    sdk: flutter
  injectable: ^2.0.0  # 请检查最新版本号
  get_it: ^7.2.0  # 请检查最新版本号

然后运行flutter pub get来安装依赖。

2. 配置Injectable

创建一个新的Dart文件,例如injection.dart,来配置Injectable:

import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';

// 创建GetIt实例
final getIt = GetIt.instance;

@InjectableConfig(
  asLazySingleton: true,
)
class MyInjectableConfig {}

void setupLocator() {
  // 注册依赖
  getIt.registerLazySingleton<MyService>(() => MyServiceImpl());
  getIt.registerLazySingleton<MyRepository>(() => MyRepositoryImpl(getIt<MyService>()));
}

3. 创建服务和仓库

接下来,创建你的服务和仓库类,并使用@Injectable()注解标记它们:

import 'package:injectable/injectable.dart';

@Injectable()
abstract class MyService {
  Future<String> fetchData();
}

class MyServiceImpl implements MyService {
  @override
  Future<String> fetchData() async {
    // 模拟数据获取
    await Future.delayed(Duration(seconds: 2));
    return "Data fetched!";
  }
}

@Injectable()
abstract class MyRepository {
  Future<String> getDataFromService();
}

class MyRepositoryImpl implements MyRepository {
  final MyService _service;

  MyRepositoryImpl(this._service);

  @override
  Future<String> getDataFromService() async {
    return await _service.fetchData();
  }
}

4. 在应用入口初始化

在你的应用入口文件(通常是main.dart)中,调用setupLocator来初始化依赖注入:

import 'package:flutter/material.dart';
import 'injection.dart';

void main() {
  // 初始化依赖注入
  setupLocator();

  runApp(MyApp());
}

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

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    super.initState();
    final myRepository = getIt<MyRepository>();
    myRepository.getDataFromService().then((data) {
      print(data); // 输出: Data fetched!
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Injectable Example'),
      ),
      body: Center(
        child: Text('Check console for fetched data'),
      ),
    );
  }
}

5. 运行应用

现在你可以运行你的Flutter应用。你应该会在控制台中看到输出"Data fetched!",这表明依赖注入已成功实现。

总结

通过以上步骤,你已经成功在Flutter项目中使用injectable_micropackages插件实现了依赖注入。这个插件大大简化了依赖管理的复杂性,并提供了强大的功能来支持复杂的应用架构。

回到顶部