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)}');
}
类似于Class
,Method
,Field
就是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
更多关于Flutter服务提供插件service_provider_dart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
service_provider_dart
是一个用于在 Flutter 中管理依赖注入的插件。它允许你注册和解析服务,从而简化应用程序中的依赖管理。以下是如何使用 service_provider_dart
的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 service_provider_dart
依赖:
dependencies:
flutter:
sdk: flutter
service_provider_dart: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get
以安装依赖。
2. 创建服务
你可以创建一些服务类,例如:
class MyService {
void doSomething() {
print('Doing something!');
}
}
class AnotherService {
void doAnotherThing() {
print('Doing another thing!');
}
}
3. 注册服务
在应用程序的入口点(通常是 main.dart
文件)中,你可以使用 ServiceProvider
来注册这些服务:
import 'package:flutter/material.dart';
import 'package:service_provider_dart/service_provider_dart.dart';
void main() {
// 注册服务
ServiceProvider.registerSingleton<MyService>(MyService());
ServiceProvider.registerSingleton<AnotherService>(AnotherService());
runApp(MyApp());
}
4. 解析和使用服务
在需要的地方,你可以通过 ServiceProvider
来解析并使用这些服务:
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
// 解析服务
final myService = ServiceProvider.resolve<MyService>();
final anotherService = ServiceProvider.resolve<AnotherService>();
// 使用服务
myService.doSomething();
anotherService.doAnotherThing();
return MaterialApp(
title: 'Service Provider Example',
home: Scaffold(
appBar: AppBar(
title: Text('Service Provider Example'),
),
body: Center(
child: Text('Check the console for output!'),
),
),
);
}
}
5. 其他注册方式
除了 registerSingleton
,ServiceProvider
还支持其他注册方式,例如:
registerTransient
: 每次解析时都会创建一个新的实例。registerLazySingleton
: 在第一次解析时创建实例,之后每次解析都返回相同的实例。
ServiceProvider.registerTransient<MyService>((_) => MyService());
ServiceProvider.registerLazySingleton<AnotherService>((_) => AnotherService());
6. 依赖注入
你还可以通过构造函数注入依赖:
class MyApp extends StatelessWidget {
final MyService myService;
final AnotherService anotherService;
MyApp({required this.myService, required this.anotherService});
[@override](/user/override)
Widget build(BuildContext context) {
myService.doSomething();
anotherService.doAnotherThing();
return MaterialApp(
title: 'Service Provider Example',
home: Scaffold(
appBar: AppBar(
title: Text('Service Provider Example'),
),
body: Center(
child: Text('Check the console for output!'),
),
),
);
}
}
void main() {
ServiceProvider.registerSingleton<MyService>(MyService());
ServiceProvider.registerSingleton<AnotherService>(AnotherService());
runApp(MyApp(
myService: ServiceProvider.resolve<MyService>(),
anotherService: ServiceProvider.resolve<AnotherService>(),
));
}