Flutter服务提供插件service_provider_dart的使用

Flutter服务提供插件service_provider_dart的使用

一、背景

在做Flutter侧业务开发时,不同同学会负责不同的业务模块,也会使用一些类似于登录、跳转等非业务的基础功能。如果不把这些功能抽象出来统一管理的话,业务之间会耦合严重,不便于后续业务的拆分和演进。基于此实现服务解耦功能,类似于Java中的SPI。

二、如何做

服务解耦就是需要将抽象和实现分离,也就是具体的业务我们需要抽象成一个接口,具体的业务来实现这个接口。最主要的是我们暴露给业务方的需要是抽象也就是接口,隐藏我们实现类的逻辑。那么就可看出来需要解决以下两个问题:

  • 抽象 → 实现,如何绑定
  • 业务方如何获取

具体实现我们可以参照Android解决此问题的方式,可以使用注解+代码生成的方式来实现,Dart中也提供了注解。那么以上两步的解决方案就是:

  • 绑定可以使用注解来做
  • 业务方如何获取可以通过编译期代码生成,统一的ServiceProvider来提供服务

2.1 抽象和服务的关联

下文都以登录为例:

我们先将服务的接口和实现分离,这个很好做:

抽象的接口:

/// 登录接口
abstract class ILoginService implements IService {
  void login();
  void logout();
}

/// 登录实现,这里使用了注解进行绑定
@ServiceBindAnnotation(ILoginService)
class LoginService implements ILoginService {
  @override
  void init() {}

  @override
  void getUserInfo() {
    print('getUserInfo');
  }

  @override
  void login() {
    print('login');
  }
}

2.2 如何获取

上面说了可以通过编译期代码生成,有以下几个方式:

  • 自己按照格式来字符串生成文件
  • 使用mustache4dart2模板代码生成
  • 使用code_builder类似于ASM的方式

第1种方式自己写格式处理等不好做,也没有代码相关限制,加上后期维护成本高的原因所以不选择第一种;第2中方式是闲鱼的路由框架使用的开源库,但是现在不支持空安全;所以最后选择了第3种方式,它是Flutter官方提供的,功能强大,但是没有过多地介绍和API文档不够完善,只能在开发中逐渐摸索。

集中代码生成我们直接看代码:

String write(BuildStep buildStep) {
    DartEmitter emitter = DartEmitter.scoped();
    var library = Library((b) {
      b.body.addAll([
        // 生成类
        Class((builder) {
          builder.name = "ServiceProviderInternal";
          builder.fields.addAll([
            Field((fieldBuilder) {
              fieldBuilder.name = "_cache";
              fieldBuilder.type = refer("Map<Type, IService>");
              fieldBuilder.modifier = FieldModifier.var$;
              fieldBuilder.assignment = const Code("{}");
              fieldBuilder.modifier = FieldModifier.final$;
            })
          ]);
          builder.methods.addAll(
            // 生成方法
            [
              Method((methodBuilder) {
                methodBuilder.name = "getService";
                methodBuilder.body = _generatorGetService(eachServiceInfoMaps);
                methodBuilder.types.add(refer('T extends IService'));
                methodBuilder.returns = refer('T');
              }),
              Method((methodBuilder) {
                methodBuilder.name = "_getService";
                methodBuilder.body = _generatorInnerGetService();
                methodBuilder.types.add(refer('T extends IService'));
                methodBuilder.requiredParameters.add(Parameter((builder) {
                  builder.name = "impl";
                  builder.type = refer('IService');
                }));
                methodBuilder.returns = refer('T');
              })
            ],
          );
        }),
      ]);
      // 导入引用
      b.directives.clear();
      b.directives.addAll(allImportSet);
    });
    return DartFormatter().format('${library.accept(emitter)}');
  }

类似于ClassMethodField就是code_builder提供生成类的API,基本使用看注释就可以了;

根据以上分析再加上编译期注解生成,我们看一下最后生成的代码:

// GENERATED CODE - DO NOT MODIFY BY HAND

// **************************************************************************
// Generator: ServiceProvider
// **************************************************************************

import 'package:service_provider/interface/service_interface.dart';
import 'package:service_provider_sample/sample/login.service.service.dart';
import 'package:service_provider_sample/sample/login_service.service.find.dart';

class ServiceProviderInternal {
  final Map<Type, IService> _cache = {};

  T getService<T extends IService>() {
    switch (T) {
      case ILoginService:
        return _getService<T>(LoginService());
      default:
        throw Exception("ServiceProviderInternal not find service!!!!!");
    }
  }

  T _getService<T extends IService>(IService impl) {
    if (!_cache.containsKey(T)) {
      _cache[T] = impl;
      impl.init();
    }
    return _cache[T] as T;
  }
}

更多关于Flutter服务提供插件service_provider_dart的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter服务提供插件service_provider_dart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


service_provider_dart 是一个用于 Flutter 的服务提供者插件,它允许你在应用中注册和解析依赖项。这个插件类似于其他依赖注入(DI)框架,但更轻量且易于使用。通过 service_provider_dart,你可以将服务的实现与接口分离,从而更容易进行单元测试和代码维护。

安装

首先,你需要在 pubspec.yaml 文件中添加 service_provider_dart 依赖:

dependencies:
  flutter:
    sdk: flutter
  service_provider_dart: ^1.0.0

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

基本用法

1. 注册服务

你可以在应用的启动阶段注册服务。ServiceProvider 是一个单例,你可以在任何地方访问它。

import 'package:service_provider_dart/service_provider_dart.dart';

void main() {
  // 注册一个服务
  ServiceProvider.instance.registerSingleton<MyService>(MyServiceImpl());

  runApp(MyApp());
}

2. 解析服务

在需要使用服务的地方,你可以通过 ServiceProvider 来解析服务。

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    // 解析服务
    MyService myService = ServiceProvider.instance.resolve<MyService>();

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Service Provider Example'),
        ),
        body: Center(
          child: Text(myService.getMessage()),
        ),
      ),
    );
  }
}

3. 定义服务和实现

你通常需要定义一个接口(或抽象类)和它的实现。

abstract class MyService {
  String getMessage();
}

class MyServiceImpl implements MyService {
  [@override](/user/override)
  String getMessage() {
    return 'Hello from MyService!';
  }
}

高级用法

1. 注册工厂方法

你可以使用工厂方法来注册服务,每次解析时都会调用工厂方法创建新的实例。

ServiceProvider.instance.registerFactory<MyService>(() => MyServiceImpl());

2. 注册单例

如果你希望在整个应用中共享同一个实例,可以使用 registerSingleton

ServiceProvider.instance.registerSingleton<MyService>(MyServiceImpl());

3. 注册懒加载单例

有时你可能希望服务在第一次使用时才初始化,可以使用 registerLazySingleton

ServiceProvider.instance.registerLazySingleton<MyService>(() => MyServiceImpl());

4. 注册带参数的服务

你可以注册带参数的服务,并在解析时传递参数。

ServiceProvider.instance.registerFactoryParam<MyService, String, void>(
  (param, _) => MyServiceImplWithParam(param),
);

// 解析时传递参数
MyService myService = ServiceProvider.instance.resolveWithParam<MyService, String>('param value');

示例完整代码

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

void main() {
  // 注册服务
  ServiceProvider.instance.registerSingleton<MyService>(MyServiceImpl());

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    // 解析服务
    MyService myService = ServiceProvider.instance.resolve<MyService>();

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Service Provider Example'),
        ),
        body: Center(
          child: Text(myService.getMessage()),
        ),
      ),
    );
  }
}

abstract class MyService {
  String getMessage();
}

class MyServiceImpl implements MyService {
  [@override](/user/override)
  String getMessage() {
    return 'Hello from MyService!';
  }
}
回到顶部