Flutter依赖注入插件modular_di的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter依赖注入插件modular_di的使用

简介

Modular DI 是一个用于Flutter应用程序的依赖注入库,它允许你通过模块化的方式来组织和管理依赖。Modular DI 提供了一个简单而灵活的方式来将你的应用拆分为多个模块,并在这些模块之间进行依赖注入。以下是关于如何使用 Modular DI 的详细说明和一个完整的示例项目。

功能特点

  • Works with whatever router you love:支持与任何路由管理器(如 Go Router、Auto Route)集成。
  • Keep your app tidy with a simple module system:通过模块系统保持应用结构清晰。
  • Easy dependency injection:基于 auto_injector 实现简单的依赖注入。
  • Modules can talk to each other through imports:模块之间可以通过导入相互通信。
  • Modules load up and clean up smoothly:模块可以平滑地加载和清理。
  • Drop in the ModuleWidget wherever you need it:可以在需要的地方使用 ModuleWidget
  • Testing is a breeze with mock replacements:测试时可以轻松替换依赖。
  • Lightning-fast dependency resolution using directed acyclic graphs:使用有向无环图实现快速的依赖解析。

快速开始

1. 添加依赖

pubspec.yaml 文件中添加 modular_di 依赖:

dependencies:
  modular_di: ^latest_version  # 请替换为最新版本

2. 创建模块

创建一个模块类,继承自 Module,并在其中注册依赖项。例如,创建一个 UserModule

class UserModule extends Module {
  [@override](/user/override)
  List<Type> imports = []; // 如果需要导入其他模块,请在此处添加

  [@override](/user/override)
  FutureOr<void> registerBinds(InjectorRegister i) {
    // 注册依赖项
    i.addSingleton<UserRepository>(() => UserRepositoryImpl());
    i.addSingleton<UserService>(() => UserServiceImpl());
  }
}

3. 初始化模块

main.dart 中初始化模块。你可以一次性注册所有模块,也可以分别注册模块,最后统一初始化。

一次性注册并初始化模块:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 注册并初始化模块
  await ModulesManager.instance.initModules([
    UserModule(),
    AuthModule(),
  ]);

  runApp(const MyApp());
}

分别注册模块,最后统一初始化:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 注册 CoreModule
  ModulesManager.instance.registerModule(CoreModule());

  // 注册 User 和 Auth 模块
  ModulesManager.instance.registerModules([
    UserModule(),
    AuthModule(),
  ]);

  // 初始化所有已注册的模块
  await ModulesManager.instance.initRegisteredModules();

  runApp(const MyApp());
}

4. 使用 ModuleWidget 访问依赖

在需要访问依赖的页面中使用 ModuleWidget,并通过 Module.get<T>() 获取依赖项。例如:

class UserScreen extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return ModuleWidget<UserModule>(
      child: Builder(
        builder: (context) {
          // 获取依赖项,不监听变化
          final userService = Module.get<UserService>(context);
          return UserContent(service: userService);
        },
      ),
    );
  }
}

5. 监听模块变化

如果你希望在模块发生变化时重新构建 widget,可以在获取依赖时设置 listen: true。例如:

class UserProfileWidget extends StatefulWidget {
  [@override](/user/override)
  State<UserProfileWidget> createState() => _UserProfileWidgetState();
}

class _UserProfileWidgetState extends State<UserProfileWidget> {
  late UserService _userService;

  [@override](/user/override)
  void didChangeDependencies() {
    super.didChangeDependencies();
    // 监听变化 - 当前模块或导入的模块被重置时,widget 会重新构建
    _userService = Module.get<UserService>(context, listen: true);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Text(_userService.username);
  }
}

6. 模块之间的依赖

模块可以依赖其他模块,通过 imports 属性来声明。例如,ProfileModule 依赖于 UserModule

class ProfileModule extends Module {
  [@override](/user/override)
  List<Type> imports = [UserModule]; // 导入 UserModule 的依赖

  [@override](/user/override)
  FutureOr<void> registerBinds(InjectorRegister i) {
    i.addSingleton<ProfileService>(ProfileServiceImpl.new);
  }
}

7. 依赖注入类型

Modular DI 支持多种依赖注入方式:

  • SingletonaddSingleton<T>() - 创建一个全局唯一的实例。
  • Lazy SingletonaddLazySingleton<T>() - 第一次请求时才创建实例。
  • Factoryadd<T>() - 每次请求时都创建新的实例。
  • InstanceaddInstance<T>() - 注册一个已经存在的实例。
  • Replacereplace<T>() - 替换现有的注册(适用于测试)。

8. 日志功能

Modular DI 内置了日志系统,默认是关闭的。你可以根据需要启用或禁用日志:

import 'package:modular_di/logger.dart';

// 启用日志
Logger.enable();

// 禁用日志
Logger.disable();

日志仅在调试模式下打印,因此可以安全地保留日志代码在生产环境中。

完整示例项目

以下是一个完整的示例项目,展示了如何使用 Modular DI 来管理多个模块及其依赖关系。

项目结构

lib/
├── features/
│   ├── core/
│   │   └── core_module.dart
│   ├── home/
│   │   └── home_module.dart
│   ├── message/
│   │   └── message_module.dart
│   └── profile/
│       └── profile_module.dart
└── main.dart

core_module.dart

import 'package:modular_di/modular_di.dart';

class CoreModule extends Module {
  [@override](/user/override)
  FutureOr<void> registerBinds(InjectorRegister i) {
    // 注册核心依赖
    i.addSingleton<CoreService>(() => CoreServiceImpl());
  }
}

home_module.dart

import 'package:modular_di/modular_di.dart';

class HomeModule extends Module {
  [@override](/user/override)
  FutureOr<void> registerBinds(InjectorRegister i) {
    // 注册首页依赖
    i.addSingleton<HomeService>(() => HomeServiceImpl());
  }
}

message_module.dart

import 'package:modular_di/modular_di.dart';

class MessageModule extends Module {
  [@override](/user/override)
  FutureOr<void> registerBinds(InjectorRegister i) {
    // 注册消息依赖
    i.addSingleton<MessageService>(() => MessageServiceImpl());
  }
}

profile_module.dart

import 'package:modular_di/modular_di.dart';

class ProfileModule extends Module {
  [@override](/user/override)
  List<Type> imports = [UserModule]; // 导入 UserModule 的依赖

  [@override](/user/override)
  FutureOr<void> registerBinds(InjectorRegister i) {
    // 注册个人资料依赖
    i.addSingleton<ProfileService>(ProfileServiceImpl.new);
  }
}

main.dart

import 'package:flutter/material.dart';
import 'package:modular_di/logger.dart';
import 'package:modular_di/modular_di.dart';

import 'features/core/core_module.dart';
import 'features/home/home_module.dart';
import 'features/message/message_module.dart';
import 'features/profile/profile_module.dart';

/// ### 应用程序的所有模块
/// 用于初始化依赖
final modules = <Module>[
  CoreModule(),
  MessageModule(),
  HomeModule(),
  ProfileModule(),
];

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  Logger.enable();  // 启用日志
  await ModulesManager.instance.initModules(modules);  // 初始化模块
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      initialRoute: '/',
      routes: {
        '/': (context) => const ModuleWidget<HomeModule>(child: HomeScreen()),
        '/message': (context) => const ModuleWidget<MessageModule>(child: MessageScreen()),
        '/profile': (context) => const ModuleWidget<ProfileModule>(child: ProfileScreen()),
      },
    );
  }
}

// 示例页面
class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    final homeService = Module.get<HomeService>(context);
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(child: Text(homeService.getMessage())),
    );
  }
}

class MessageScreen extends StatelessWidget {
  const MessageScreen({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    final messageService = Module.get<MessageService>(context);
    return Scaffold(
      appBar: AppBar(title: Text('Message')),
      body: Center(child: Text(messageService.getMessage())),
    );
  }
}

class ProfileScreen extends StatelessWidget {
  const ProfileScreen({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    final profileService = Module.get<ProfileService>(context);
    return Scaffold(
      appBar: AppBar(title: Text('Profile')),
      body: Center(child: Text(profileService.getUsername())),
    );
  }
}

服务实现

为了使示例更完整,以下是各个服务的简单实现:

core_service.dart

class CoreService {
  String getMessage() {
    return "This is the core service.";
  }
}

class CoreServiceImpl implements CoreService {
  [@override](/user/override)
  String getMessage() {
    return "This is the core service implementation.";
  }
}

home_service.dart

class HomeService {
  String getMessage() {
    return "Welcome to the home page!";
  }
}

class HomeServiceImpl implements HomeService {
  [@override](/user/override)
  String getMessage() {
    return "Welcome to the home page! This is the implementation.";
  }
}

message_service.dart

class MessageService {
  String getMessage() {
    return "You have no new messages.";
  }
}

class MessageServiceImpl implements MessageService {
  [@override](/user/override)
  String getMessage() {
    return "You have 3 new messages!";
  }
}

profile_service.dart

class ProfileService {
  String getUsername() {
    return "Unknown User";
  }
}

class ProfileServiceImpl implements ProfileService {
  [@override](/user/override)
  String getUsername() {
    return "John Doe";
  }
}

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

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用modular_di进行依赖注入的示例代码。modular_di是一个强大的依赖注入库,与modular路由库紧密集成,但也可以独立使用。

首先,确保你的pubspec.yaml文件中添加了modular_di依赖:

dependencies:
  flutter:
    sdk: flutter
  modular_di: ^latest_version # 替换为最新版本号

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

接下来,我们来看一个具体的代码示例。

1. 创建一个服务类

首先,创建一个简单的服务类,比如一个用户服务:

// user_service.dart
import 'package:modular_di/modular_di.dart';

@Injectable()
class UserService {
  String getUserName() {
    return "John Doe";
  }
}

2. 配置依赖注入

在应用的入口文件(通常是main.dart)中配置依赖注入:

// main.dart
import 'package:flutter/material.dart';
import 'package:modular_di/modular_di.dart';
import 'user_service.dart';

void main() {
  // 初始化依赖注入模块
  ModularDi.init();

  // 注册依赖
  ModularDi.bind<UserService>((i) => UserService());

  runApp(MyApp());
}

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

3. 在组件中使用依赖注入

现在,我们可以在组件中使用ModularDi.get()来获取依赖注入的服务:

// home_screen.dart
import 'package:flutter/material.dart';
import 'package:modular_di/modular_di.dart';
import 'user_service.dart';

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 获取UserService实例
    final UserService userService = ModularDi.get<UserService>();

    return Scaffold(
      appBar: AppBar(
        title: Text('Home Screen'),
      ),
      body: Center(
        child: Text('User Name: ${userService.getUserName()}'),
      ),
    );
  }
}

4. 使用模块(可选)

如果你使用的是modular库,你可以将依赖注入配置放在模块中。这里是一个简单的示例:

// app_module.dart
import 'package:modular/modular.dart';
import 'user_service.dart';

@Module()
abstract class AppModule {
  @Bind()
  UserService get userService => UserService();
}

然后在main.dart中使用这个模块:

// main.dart (使用模块版本)
import 'package:flutter/material.dart';
import 'package:modular/modular.dart';
import 'app_module.dart';

void main() {
  // 初始化Modular
  Modular.init(modules: [
    AppModule(),
  ]);

  runApp(ModularApp(module: AppModule(), child: MyApp()));
}

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

在模块版本的HomeScreen中,你可以直接使用Modular.get<UserService>()来获取服务:

// home_screen.dart (使用模块版本)
import 'package:flutter/material.dart';
import 'package:modular/modular.dart';
import 'user_service.dart';

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 获取UserService实例
    final UserService userService = Modular.get<UserService>();

    return Scaffold(
      appBar: AppBar(
        title: Text('Home Screen'),
      ),
      body: Center(
        child: Text('User Name: ${userService.getUserName()}'),
      ),
    );
  }
}

以上就是在Flutter中使用modular_di进行依赖注入的示例代码。根据你的项目需求,你可以选择直接使用ModularDi或者结合modular库使用模块化的方式来管理依赖注入。

回到顶部