Flutter插件darin的使用方法详解

Flutter插件darin的使用方法详解

Flutter插件darin特性

  • 在Dart中以尽可能接近DSL的方式定义依赖项
  • 使用作用域来控制对象的生命周期(依赖于垃圾回收机制)
  • 半自动的依赖解析
  • 没有魔法,所有功能都是通过常规Dart代码实现,没有不必要的代码生成

Flutter插件darin原则

  • 使用工厂方法每次请求时获取新实例
  • 使用作用域获取在整个作用域生命周期内持久化的实例
  • 作用域是通用的,如果你想要单例,只需在一个始终存在的作用域中创建一个作用域
  • 没有内置全局/静态容器,如果你想拥有一个,自己管理它
  • 作用域存在于层次结构中,首先创建最宽的作用域,然后逐层创建更窄的作用域
  • 如果当前作用域中找不到所需的依赖项,Darin会尝试在所有父作用域中解析
  • 你的作用域将拥有所有者。概念上讲,理解作用域与其生命周期的绑定很重要。作用域应该在比其所有者更早被丢弃,否则会导致内存泄漏

开始使用

导入包:

dependencies:
  darin:

Flutter插件darin使用

创建你的作用域:

final scope = Scope((scope) => scope
    ..factory<Interface1>((scope) => Implementation1())
    ..scoped<Interface2>((scope) => Implementation2(scope.get<Interface1>()))
    ..scope<Interface4>((scope) => scope
        ..factory<Interface4>((scope) => Implementation4(scope.get<Interface3>()))
        ..scoped<Interface5>((scope) => Implementation5(
            scope.get<Interface3>(),
            scope.get<Interface4>(),
        ))
    )
);

你可以将应用特定部分的依赖项分离到多个作用域(甚至跨包),并在一个地方组合它们:

final scope = Scope.fromScopes([
    scopeFromAPackage(),
    scopeFromBPackage(),
    scopeFromCPackage(),
]);

使用此scope作为依赖注入容器。你可以将其用作服务定位器,但我建议避免这样做,而是定义所有类的提供者在你的作用域和子作用域中,并仅获取根对象,让Darin负责解析依赖项。如果你选择这种方式,请不要忘记利用提供者支持或创建子作用域。

获取你的依赖项:

final MyDep = scope.get<MyDep>();

获取更窄的作用域:

// 所有者将是 `existingObject`,并且在子作用域中可用
final subscope = scope.scope<MyDep>(existingObject);

// 或者

// 作用域的所有者将由 `scope` 提供,并且在子作用域中可用
final subscope = scope.scopeProvided(MyDep);

路线图

  • ✅ 基本注入与作用域支持
  • ✅ Flutter集成通过InheritedWidget
  • ✅ 支持Set/Map
  • ✅ 获取提供者类似于获取依赖项
  • ❌ 工厂参数

其他信息

对于Flutter集成,参见Darin Flutter

对Koin用户

Koin设计为让你能够在应用程序的任何位置获取依赖注入容器,即使你没有引用。我的猜测是这样做是为了让你可以在Android Activity中使用val myDep by inject<MyDep>(),因为在这些Activity中你没有任何可以利用的上下文/作用域,因此需要静态访问器。这在Flutter中不是问题,因为你在Flutter中实际控制屏幕的创建方式,以及你在BuildContext中拥有的内容。因此,我没有包含任何静态内容,这可能会允许你依赖全局引用。有一些静态函数遵循Flutter模式(想想SomethingFluttery.of(BuildContext)),但这些依赖于BuildContext,因此你不会使用任何全局引用,即使是幕后操作也是如此。这是为了好理由,因为你总是可以为不同的原因设置并行作用域,而不会像Koin中的Darin.start()那样互相覆盖。

示例代码

import 'package:darin/darin.dart';

import '_dependencies.dart';

/// 这个例子是一个企业级的Hello World(意味着绝对复杂)
/// 以演示依赖项及其如何定义DI配置。
/// 它展示了如何创建作用域、作用域化依赖项以及使用提供者。
///
/// 我不想过度解释代码,但一些解释有助于理解:
/// - 这个Hello World“访问地点”,并从那里问候(意思是打印的行具有地点)
/// - 每次访问都在自己的作用域中,因此当你使用位置提供者时,
///   你会自动获取属于该访问的位置。
/// - 仅为了演示如何作用域化依赖项,[RandomNameProvider]被作用域化
///   (在最顶层作用域中,所以技术上来说它是单例的),因此记住第一次使用时随机化的值
///   对整个应用生命周期有效。
void main() {
  Scope mainScope = buildMainScope();

  var locations = [Location("GitHub"), Location("pub.dev")];
  for (var location in locations) {
    var scope = mainScope.scope(location);
    scope.get<GreetingPrinter>().printGreeting();
  }
}

// 下面是所有与Darin相关的代码

/// 构建此示例中的主要作用域。这被视为单例,
/// 因为应用程序的逻辑在整个应用生命周期中保持它。
Scope buildMainScope() {
  return Scope(
    (builder) {
      return builder
        ..scoped<NameProvider>((scope) => RandomNameProvider())
        ..factory<GreetingPrinter>(
          (scope) => ConsoleGreetingPrinter(scope.get()),
        )
        ..scope<Location>(
          (builder) => builder
            ..factory(
              (scope) => Greeter(scope.get(), scope.getProvider()),
            ),
        );
    },
  );
}

更多关于Flutter插件darin的使用方法详解的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter插件darin的使用方法详解的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,在探讨一个未明确定义的Flutter插件(如 darin)时,我们可以基于插件名称和常见的Flutter插件功能进行合理推测,并展示如何使用一个假设的插件接口。请注意,以下代码是基于假设构建的,因为实际的 darin 插件可能并不存在或者其功能完全不同。

假设 darin 插件是一个用于数据处理的库,可能提供了一些用于数据转换、加密或解密的功能。以下是一个如何使用这种假设插件的示例代码:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 darin 插件的依赖(注意:这里的 darin 是假设的,实际使用时需要替换为真实插件名):

dependencies:
  flutter:
    sdk: flutter
  darin: ^0.0.1  # 假设的版本号,实际使用时需要替换为真实版本号

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

2. 导入插件

在你的 Dart 文件中导入 darin 插件:

import 'package:darin/darin.dart';

3. 使用插件功能

假设 darin 插件提供了一个数据转换功能,比如将字符串加密或解密。以下是一个使用这种功能的示例:

void main() {
  // 假设的加密/解密功能使用示例
  String originalData = "Hello, Flutter!";
  String encryptedData;
  String decryptedData;

  // 加密数据
  try {
    encryptedData = Darin.encrypt(originalData);
    print("Encrypted Data: $encryptedData");
  } catch (e) {
    print("Encryption failed: $e");
  }

  // 解密数据
  try {
    decryptedData = Darin.decrypt(encryptedData);
    print("Decrypted Data: $decryptedData");
  } catch (e) {
    print("Decryption failed: $e");
  }
}

4. 假设的插件接口定义

由于我们不知道 darin 插件的真实接口,以下是一个假设的插件接口定义,用于说明可能的实现方式:

library darin;

export 'src/darin_base.dart';

class Darin {
  // 假设的加密方法
  static String encrypt(String data) {
    // 这里应该实现加密逻辑,但这里只是返回一个假设的加密字符串
    return base64Encode(utf8.encode(data)) + "_encrypted";
  }

  // 假设的解密方法
  static String decrypt(String encryptedData) {
    // 去除假设的加密标记,并进行解密
    if (encryptedData.endsWith("_encrypted")) {
      String encodedData = encryptedData.substring(0, encryptedData.length - "_encrypted".length);
      List<int> decodedBytes = base64Decode(encodedData);
      return utf8.decode(decodedBytes);
    } else {
      throw Exception("Invalid encrypted data format");
    }
  }
}

注意:上述 Darin 类的实现只是为了演示目的,并不是实际的加密/解密逻辑。在实际应用中,应该使用安全的加密库来处理敏感数据。

由于 darin 插件是未知的,上述代码和假设可能并不符合实际情况。在实际开发中,你应该参考插件的官方文档或源代码来了解其真实功能和用法。

回到顶部