Flutter未知功能探索插件catalyst_builder的使用

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

Flutter未知功能探索插件catalyst_builder的使用

Catalyst Builder 简介

GitHub license GitHub issues GitHub Workflow Status Pub Pub Points Pub Publisher Pub Popularity Pub Likes

Catalyst Builder 是一个用于Dart和Flutter的依赖注入提供者构建器。它简化了依赖注入的过程,使开发者只需在服务类上添加@Service注解,通过build_runner即可自动生成服务提供者。

安装

请按照以下步骤安装:

  1. pubspec.yaml中添加依赖:
dev_dependencies:
  build_runner: ^2.2.0
  catalyst_builder: ^latest_version
  1. 运行flutter pub get以获取依赖包。

使用方法

基本用法

创建服务

在需要注册为服务的类上添加@Service注解:

@Service()
class MyService {}

注册服务提供者

在入口文件(如main.dart)中添加@GenerateServiceProvider注解:

import 'package:catalyst_builder/catalyst_builder.dart';

@GenerateServiceProvider()
void main() {
  // ...
}

构建服务提供者

运行以下命令生成服务提供者文件:

flutter pub run build_runner build

或者使用watch模式自动更新:

flutter pub run build_runner watch

使用服务提供者

生成的服务提供者文件通常命名为*.catalyst_builder.g.dart。导入该文件并创建服务提供者的实例:

import 'my_entrypoint.catalyst_builder.g.dart';

void main() {
  var provider = DefaultServiceProvider();
  provider.boot();

  var myService1 = provider.resolve<MyService>();
  MyService myService2 = provider.resolve();
}

高级用法

服务生命周期

可以指定服务的生命周期,默认为单例(Singleton),也可以设置为瞬态(Transient):

@Service(
  lifetime: ServiceLifetime.singleton,
)
class SingletonService {}

@Service(
  lifetime: ServiceLifetime.transient,
)
class TransientService {}
生命周期 描述
Singleton 实例存储在提供者中,每次解析返回相同的实例
Transient 每次解析时返回新的实例

暴露接口

可以通过exposeAs参数暴露服务的接口:

abstract class Transport {
  void transferData(String data);
}

@Service(exposeAs: Transport)
class ConsoleTransport implements Transport {
  @override
  void transferData(String data) {}
}

abstract class ChatProvider {
  Transport transport;

  Future<void> sendChatMessage(String message);
}

@Service(exposeAs: ChatProvider)
class CoolChatProvider implements ChatProvider {
  @override
  Transport transport;

  CoolChatProvider(this.transport);

  @override
  Future<void> sendChatMessage(String message) {}
}

void main() {
  var provider = DefaultServiceProvider();
  var chatService = provider.resolve<ChatProvider>();

  print(chatService is CoolChatProvider); // true
  print(chatService.transport is ConsoleTransport); // true
}

预加载服务

使用@Preload注解可以在启动时预加载服务:

@Service()
@Preload()
class MyService {
  MyService() {
    print('Service was created');
  }
}

void main() {
  ServiceProvider provider;
  provider.boot(); // 打印 "Service was created"
  provider.resolve<MyService>(); // 不打印任何内容
}

参数注入

可以通过名称注入参数:

@Service()
class MyService {
  String username;

  MyService(@Inject(parameter: 'senderUserName') this.username);
}

void main() {
  ServiceProvider provider;
  provider['senderUserName'] = 'Test 2';
  provider.boot();

  var myService = provider.resolve<MyService>();

  print(myService.username); // Test 2 
}

动态注册服务

可以在运行时注册服务:

void main() {
  var provider = ExampleProvider();

  provider.register(
        (provider) => MySelfRegisteredService(provider.resolve()),
  );

  var selfRegistered = provider.resolve<MySelfRegisteredService>();
  selfRegistered.sayHello();
}

创建子提供者

可以创建带有额外服务或参数的子提供者:

void main() {
  var provider = ExampleProvider();

  var newProvider = provider.enhance(
    parameters: {
      'foo': 'overwritten',
    },
    services: [
      LazyServiceDescriptor<MySelfRegisteredService>(
            (p) => MySelfRegisteredService(p.resolve(), p.parameters['foo']),
        const Service(exposeAs: SelfRegisteredService),
      ),
    ],
  );

  var mySvc = newProvider.resolve<SelfRegisteredService>();
  expect(mySvc.foo, equals('overwritten'));
}

标签化服务

可以给服务打标签,方便分组管理:

@Service(tags: ['#groupTag', '#anotherTag'])
class MyService1 {}

@Service(tags: ['#groupTag', '#anotherDifferentTag'])
class MyService2 {}

void main() {
  var provider = ExampleProvider();
  provider.boot();

  var groupTagServices = provider.resolveByTag('#groupTag');
  // groupTagServices = [MyService1, MyService2]

  var anotherTagServices = provider.resolveByTag('#anotherTag');
  // anotherTagServices = [MyService1]

  var anotherDifferentTagServices = provider.resolveByTag('#anotherDifferentTag');
  // anotherDifferentTag = [MyService2]

  var nonExistingTagServices = provider.resolveByTag('#nonExistingTag');
  // servicesWithUnknownTag = []
}

注入标签化服务

可以通过标签注入一组服务:

abstract class MyServiceBase {}

@Service(tags: ['#groupTag', '#anotherTag'])
class MyService1 extends MyServiceBase {}

@Service(tags: ['#groupTag', '#anotherDifferentTag'])
class MyService2 extends MyServiceBase {}

@Service()
class ServiceWithDeps {
  
  ServiceWithDeps(
      @Inject(tag: '#groupTag') List<MyServiceBase> services,
  ) {
    // services 包括 MyService1 和 MyService2
  }
}

示例代码

import 'package:catalyst_builder/catalyst_builder.dart';
import './src/manually_wired_service.dart';

export './public_api.dart';
export './src/manually_wired_service.dart';
export 'example.catalyst_builder.g.dart';

/**
 * Export the catalyst_exports that the watch command can recompile the
 * ServiceProvider when the dependencies changes.
 */
export 'relative_deps_exports.dart';

@Preload()
@GenerateServiceProvider()
@ServiceMap(services: {
  ManuallyWiredServiceImplementation: Service(
    exposeAs: ManuallyWiredService,
  ),
})
void main() {
  var provider = DefaultServiceProvider();
  provider.boot();

  var manuallyWiredService = provider.resolve<ManuallyWiredService>();
  manuallyWiredService.doSomething();
}

以上是关于catalyst_builder插件的详细使用说明和示例代码,希望对你有所帮助。如果你有任何问题或需要进一步的帮助,请随时提问!


更多关于Flutter未知功能探索插件catalyst_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter未知功能探索插件catalyst_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter开发中,catalyst_builder 是一个相对不太常见的插件,但它提供了一些独特的功能,用于在构建过程中动态生成代码或资源。虽然文档和社区资源可能有限,但我们可以基于其基本的用法来探索其功能。

首先,确保你已经在 pubspec.yaml 文件中添加了 catalyst_builder 依赖:

dependencies:
  flutter:
    sdk: flutter

dev_dependencies:
  build_runner: ^x.y.z  # 请替换为最新版本
  catalyst_builder: ^a.b.c  # 请替换为最新版本

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

catalyst_builder 的核心功能通常是通过自定义构建步骤来生成代码或资源。为了展示其基本用法,我们可以创建一个简单的示例,假设我们要生成一些 Dart 代码文件。

  1. 创建构建配置

首先,在你的项目根目录下创建一个 build.yaml 文件,用于配置构建步骤:

builders:
  generate_code:
    import: "package:catalyst_builder/builder.dart"
    builder_factories: ["generateCodeBuilder"]
    build_extensions: {".dart": [".g.dart"]}
    auto_apply: root_package
    build_to: cache

在这个配置中,我们定义了一个名为 generate_code 的构建器,它使用 catalyst_builder 包中的 generateCodeBuilder 函数。这个构建器会为每个 .dart 文件生成一个对应的 .g.dart 文件。

  1. 编写构建器逻辑

由于 catalyst_builder 的具体 API 可能会有所不同,这里我们假设需要实现一个自定义的构建器逻辑。在实际使用中,你可能需要查阅 catalyst_builder 的具体文档来了解如何编写构建器。但作为一个示例,我们可以模拟一个简单的构建器:

// lib/builder/generate_code_builder.dart
import 'package:build/build.dart';

Builder generateCodeBuilder(BuilderOptions options) {
  return (BuildStep buildStep) async {
    var inputId = buildStep.inputId;
    var input = await buildStep.readAsString(inputId);

    // 这里我们简单地将输入内容回显到生成的文件中,实际使用中你可能会有更复杂的逻辑
    var outputContent = '''
// This is auto-generated code
part of '${inputId.path.split('.dart').first}';

void generatedFunction() {
  print('Hello from generated code!');
}
''';

    var outputId = inputId.changeExtension('.g.dart');
    await buildStep.writeAsString(outputId, outputContent);
  };
}

注意:上面的代码只是一个示例,实际上 catalyst_builder 可能不支持这种直接的构建器定义方式,或者你可能需要通过其他方式(如使用其提供的特定 API)来实现类似的功能。

  1. 应用构建器

在你的 Dart 代码中,你可以像这样引用生成的代码:

// lib/main.dart
part 'main.g.dart'; // 引用生成的代码文件

void main() {
  print('Running main function');
  generatedFunction(); // 调用生成代码中的函数
}
  1. 运行构建

最后,使用 flutter pub run build_runner build 命令来运行构建过程。如果一切正常,你应该会在 .dart_tool/build/generated/ 目录下看到生成的 .g.dart 文件。

注意:上述代码和配置是基于假设和一般构建器的工作原理编写的,实际使用 catalyst_builder 时,你需要查阅其官方文档和示例来了解其具体的用法和 API。由于 catalyst_builder 不是一个广泛使用的插件,因此文档和社区支持可能有限,建议在使用前仔细阅读其源码和文档。

回到顶部