Flutter插件df_di的使用_df_di提供了实用的依赖注入(DI)框架,并结合服务类实现了无缝的状态管理

Flutter插件df_di的使用_df_di提供了实用的依赖注入(DI)框架,并结合服务类实现了无缝的状态管理

该插件提供了实用的依赖注入(DI)框架,并结合服务类实现了无缝的状态管理。此外,它还基于DI框架构建了一个新的实体组件系统(ECS)。

Flutter插件df_di特性

  • 强大的FutureOr支持,可处理同步和异步依赖及回调。
  • 可通过类型和组Entity注册依赖项,从而管理相同类型的多个依赖项。
  • 分层DI,通过子容器实现作用域依赖。
  • 可按运行时类型或泛型类型检索依赖项。
  • 工厂依赖项和延迟初始化单例依赖项。
  • 服务类自动处理注销时的清理工作。
  • 将DI系统扩展到名为“World”的ECS框架。例如:World示例

有关完整的功能列表,请参阅API参考

Flutter插件df_di快速入门

创建一个DI容器

// 在应用程序中的任何位置访问全局DI实例。
DI.global;

// 或者创建自己的DI容器。
final di = DI();

// 创建嵌套子容器,适用于模块化应用程序中的作用域依赖。
final scopedDi = di.child().child().child(groupEntity: Entity('moduleGroup'));

注册依赖项

// 注册生命、宇宙和一切的答案。
di.register<int>(42);

// 在特定组Entity下注册整数,适用于测试环境。
di.register<int>(0, groupEntity: Entity.testGroup);

// 注册Future作为依赖项。
di.register(Future.value('Hello, DI!'));
print(di.get<String>()); // Instance of 'Future<String>'

// 注册工厂或懒加载单例构造函数。
int n = 0;
di.registerLazy<int>(() => n + 1);
di.registerLazy(() => DateTime.now());

注销依赖项

// 注销特定类型。
di.unregister<int>();
di.unregisterT<int>();

// 注销所有依赖项,重置容器。
di.unregisterAll();

// 不再需要时注销子容器。
di.unregisterChild();

获取依赖项

// 获取已注册的整数依赖项。
print(di<int>()); // 42
Type intType = int;
print(di.getT<intType>()); // 42

// 获取在特定组Entity下注册的依赖项。
print(di.get<int>(groupEntity: Entity('testGroup'))); // 0

// 处理异步依赖项。
final greeting = await di.get<String>();
print(greeting); // Hello, DI!

// 获取工厂注册的依赖项。
final now = di.getFactory<DateTime>();
print(now); // 当前时间戳
await Future.delayed(Duration(seconds: 1));
final now1 = di.getFactoryT<DateTime>();
print(now1); // 一秒后的时间

实际应用示例 - UserService

final class UserService extends Service {
  final _userName = ValueNotifier<String>('Guest');

  // 供UI消费的getter。
  ValueListenable<String> get userName => _userName;

  @override
  Future<void> onInitService(_) async {
    // 模拟加载用户数据。
    await Future.delayed(Duration(seconds: 2));
    _userName.value = 'John Doe';
  }

  @override
  void onDispose() {
    _userName.dispose(); // 清理资源。
  }
}

// 注册服务。
di.registerService(UserService.new);

// 访问服务。
final userService = await di.getServiceSingleton<UserService>();
print(userService.userName.value); // John Doe

处理同步和异步服务

同步初始化和异步清理的服务
final class SyncInitAsyncDisposeService extends Service {
  // di<SyncInitAsyncDisposeService>()不会返回Future。
  @override
  void onInitService(_) {
    // 同步初始化逻辑
  }

  // di.unregister<SyncInitAsyncDisposeService>()会返回Future。
  @override
  Future<void> onDispose() async {
    // 异步清理逻辑
  }
}

// 注册并使用服务。
di.registerService(SyncInitAsyncDisposeService.new);
final service = di.getServiceSingleton<SyncInitAsyncDisposeService>();
await di.unregister<SyncInitAsyncDisposeService>();
异步初始化和同步清理的服务
final class AsyncInitSyncDisposeService extends Service {
  // di<AsyncInitSyncDisposeService>()不会返回Future。
  @override
  Future<void> onInitService(_) async {
    await Future.delayed(Duration(seconds: 3));
    // 异步初始化逻辑
  }

  // di.unregister<AsyncInitSyncDisposeService>()不会返回Future。
  @override
  void onDispose() {
    // 同步清理逻辑
  }
}

// 注册并使用服务。
di.registerService(AsyncInitSyncDisposeService.new);
final service = await di.getServiceSingleton<AsyncInitSyncDisposeService>();
di.unregister<AsyncInitSyncDisposeService>();

获取调试用状态

// 打印当前DI容器的状态。
print(di.registry.state);

// 检查特定类型是否已注册。
print(di.isRegistered<int>()); // true

使用DI框架实现实体组件系统(ECS)

这在游戏开发中特别有用,但也可用于应用开发,如管理具有动态字段可见性的复杂表单或处理具有多个用户配置文件的可定制应用。

创建可以应用于实体的各种组件
class Name extends Component {
  final String name;
  const Name(this.name);

  @override
  List<Object?> get props => [name];
}

class Vector extends Component {
  final double x;
  final double y;
  const Vector({
    this.x = 0.0,
    this.y = 0.0,
  });

  Vector add(Vector other) {
    return Vector(
      x: x + other.x,
      y: y + other.y,
    );
  }

  @override
  List<Object?> get props => [x, y];
}

class Position extends Vector {
  const Position({
    super.x = 0.0,
    super.y = 0.0,
  });

  @override
  Position add(Vector other) {
    return Position(
      x: x + other.x,
      y: y + other.y,
    );
  }
}

class Velocity extends Vector {
  const Velocity({
    super.x = 0.0,
    super.y = 0.0,
  });

  @override
  Velocity add(Vector other) {
    return Velocity(
      x: x + other.x,
      y: y + other.y,
    );
  }
}
创建一个更新实体世界的运动系统
class MovementSystem extends UpdateSystem {
  @override
  void update(World world) {
    // 获取所有具有位置和速度组件的实体。
    final entities = world.query2<Position, Velocity>();
    for (var entity in entities) {
      // 根据速度更新位置。
      final Position position = entity.getComponent();
      final Velocity velocity = entity.getComponent();
      final result = world.updateComponent(
        entity,
        position.add(velocity),
      );
      final newPosition = result.unwrap() as Position;

      // 记录更新的位置。
      print('Updated Position: (${newPosition.x}, ${newPosition.y})');
    }
  }
}

abstract class UpdateSystem {
  void update(World world);
}
在世界中移动玩家
// 创建一个新的世界供玩家或用户存在。
final world = World();

// 在世界中创建一个新玩家。
final player1 = world.createUniqueEntity();

// 用名称、位置和速度组件在世界中生成玩家。
world.addAllComponents(player1, {
  const Name('Player 1'),
  const Position(x: 0, y: 0),
  const Velocity(x: 1, y: 0),
});

// 打印当前位置。
final p0 = player1.getComponent<Position>();
print('Position 0: (${p0.x}, ${p0.y})');

// 更新世界中的运动。
final movementSystem = MovementSystem();
movementSystem.update(world);

// 打印世界更新后的位置。
final p1 = player1.getComponent<Position>();
print('Position 1: (${p1.x}, ${p1.y})');

// 打印玩家名称。
final name = player1.getComponent<Name>().name;
print('Player name: "$name"');

更多关于Flutter插件df_di的使用_df_di提供了实用的依赖注入(DI)框架,并结合服务类实现了无缝的状态管理的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter插件df_di的使用_df_di提供了实用的依赖注入(DI)框架,并结合服务类实现了无缝的状态管理的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


关于Flutter中未知功能插件df_di的使用,由于这是一个特定的、可能不广为人知的插件,我无法提供确切的官方文档或广泛认可的用法。不过,根据Flutter插件的一般使用习惯,我可以给出一个假设性的代码示例,展示如何在Flutter项目中集成和使用一个假设的依赖注入(DI)插件df_di。请注意,这里的代码是基于假设和一般经验的,实际使用时应参考插件的官方文档。

首先,确保在pubspec.yaml文件中添加了对df_di插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  df_di: ^x.y.z  # 替换为实际版本号

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

接下来,假设df_di插件提供了一个依赖注入容器和注解来标记需要注入的依赖项,我们可以按照以下方式使用它:

  1. 定义服务类
import 'package:df_di/df_di.dart';

@Injectable() // 假设df_di提供了这样的注解
class MyService {
  void doSomething() {
    print('Service is doing something!');
  }
}
  1. 设置依赖注入容器

通常,依赖注入容器需要在应用启动时配置。在Flutter中,这通常在MaterialAppCupertinoApp的构建方法中进行。

import 'package:flutter/material.dart';
import 'package:df_di/df_di.dart';
import 'my_service.dart'; // 导入上面定义的服务类

void main() {
  // 初始化依赖注入容器(假设df_di提供了这样的方法)
  DIContainer.init();

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}
  1. 在需要的地方获取服务
import 'package:flutter/material.dart';
import 'package:df_di/df_di.dart';

class MyHomePage extends StatelessWidget {
  final MyService _myService = DIContainer.get<MyService>(); // 从容器中获取服务

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo Home Page'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            _myService.doSomething(); // 使用服务
          },
          child: Text('Press Me'),
        ),
      ),
    );
  }
}

重要说明

  • 上面的代码是基于假设的,因为df_di插件的具体API和实现细节未知。
  • 实际使用时,请务必参考df_di插件的官方文档和示例代码。
  • 如果df_di插件提供了命令行工具或生成器来自动生成依赖注入代码,也应按照其指导使用。

如果df_di是一个不存在的插件名称,或者是一个特定项目内部使用的私有插件,那么上述代码将不适用,你需要根据实际的插件文档和API来调整代码。

回到顶部