在 getx 中使用 get_it 管理依赖注入
视频
https://www.youtube.com/watch?v=NBog-RdZ1fQ
https://www.bilibili.com/video/BV1EG411X7zz/
前言
上一节讲了 freezed 来强化模型 model 的功能。
今天来说下如何用 get_it 管理 getx 项目的依赖注入 Dependency Injection。
我将会改造我的 《woo实战课程》 代码来示范说明。
代码
https://github.com/ducafecat/flutter_develop_tips/tree/main/flutter_application_get_it
参考
https://pub-web.flutter-io.cn/packages/get_it
知识点
依赖注入(Dependency Injection,DI)是一种软件设计模式,用于管理对象之间的依赖关系。它是控制反转(Inversion of Control,IoC)设计模式的一种具体实现方式。
在传统的对象创建和依赖关系管理方式中,一个对象通常负责创建和管理其所依赖的其他对象。这样的设计可能导致代码之间的紧耦合,并且在测试时难以模拟和替换依赖的对象。
依赖注入通过将对象的创建和依赖关系的管理转移到外部,来解决这些问题。具体而言,依赖注入将对象的依赖通过构造函数、方法参数、属性注入等方式从外部注入到对象中,而不是由对象自身负责创建和管理依赖。这样可以实现对象之间的解耦,提高代码的可测试性、可维护性和可扩展性。
依赖注入的核心思想是:对象只关注自身的职责,而不需要关心如何创建和获取依赖的对象。依赖的对象由外部的容器或框架负责创建和注入进来。这样,对象在使用依赖时只需要声明它们的接口或抽象类,并通过依赖注入的方式获取具体的实现。
下面是一个简单的依赖注入示例:
class Logger {
void log(String message) {
print(message);
}
}
class UserService {
final Logger _logger;
UserService(this._logger);
void login(String username, String password) {
// 用户登录逻辑
_logger.log('用户登录:$username');
}
}
void main() {
final logger = Logger();
final userService = UserService(logger);
userService.login('john', 'password');
}
在上述代码中,UserService
类依赖于 Logger
类来记录日志。通过构造函数将 Logger
对象注入到 UserService
中,使得 UserService
可以在需要时使用 _logger
来记录日志。
通过依赖注入,UserService
类与 Logger
类之间实现了解耦,UserService
不需要关心 Logger
对象的创建和管理,只需要声明它所依赖的接口。这样,我们可以方便地替换或模拟 Logger
对象,以进行单元测试或灵活地切换不同的日志记录实现。
依赖注入的好处包括降低代码的耦合度、提高代码的可测试性和可维护性,以及增强代码的可扩展性和灵活性。它在许多现代的软件开发框架和库中得到广泛应用。
步骤
第一步:创建 getx 项目
猫哥这边使用 vscode 插件 "Flutter GetX Generator - 猫哥" 进行初始
不清楚的可以一进步阅读 《我写了个 vscode 插件提升 flutter getx 开发效率 79% | 猫哥》
第二步:加入 get_it
添加组件
$ flutter pub add get_it
工具类 lib/common/utils/wp_http.dart
// 拉取数据 wordpress api
class WPHttp {
late Dio _dio;
WPHttp() {
// 初始 dio
var options = BaseOptions(
baseUrl: Constants.wpApiBaseUrl,
connectTimeout: const Duration(seconds: 10), // 10000, // 10秒
receiveTimeout: const Duration(seconds: 5), // 5000, // 5秒
headers: {},
contentType: 'application/json; charset=utf-8',
responseType: ResponseType.json,
);
_dio = Dio(options);
// 拦截器
_dio.interceptors.add(RequestInterceptors());
}
...
全局注入 lib/global.dart
class Global {
static final getIt = GetIt.instance;
static Future<void> init() async {
// 注册单例 - WPHttp
getIt.registerSingleton<WPHttp>(WPHttp());
}
}
初始 main.dart
Future<void> main() async {
await Global.init();
runApp(const MyApp());
}
第三步:在 getx 控制器中使用
API 拉取数据 lib/common/api/product.dart
import 'package:flutter_application_get_it/global.dart';
import '../index.dart';
/// 商品 api
class ProductApi {
// 读取单例 wphttp
static final _getIt = Global.getIt<WPHttp>();
/// 分类列表
static Future<List<CategoryModel>> categories() async {
var res = await _getIt.get(
'/products/categories',
);
List<CategoryModel> categories = [];
for (var item in res.data) {
categories.add(CategoryModel.fromJson(item));
}
// 排序 menuOrder , 小号在前
categories.sort((a, b) => a.menuOrder!.compareTo(b.menuOrder as int));
return categories;
}
...
Global.getIt
() 通过泛型查找对象
控制器 lib/pages/product_list/controller.dart
class ProductListController extends GetxController {
ProductListController();
// 商品列表
List<ProductModel> products = [];
_initData() async {
products = await ProductApi.products(ProductsReq());
update(["product_list"]);
}
void onTap() {}
@override
void onReady() {
super.onReady();
_initData();
}
}
视图 lib/pages/product_list/view.dart
// 主视图
Widget _buildView() {
return ListView.builder(
itemCount: controller.products.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(controller.products[index].name ?? ""),
subtitle: Image.network(
controller.products[index].images?[0].src ?? "",
height: 100,
fit: BoxFit.cover,
),
);
},
);
}
@override
Widget build(BuildContext context) {
return GetBuilder<ProductListController>(
init: ProductListController(),
id: "product_list",
builder: (_) {
return Scaffold(
appBar: AppBar(title: const Text("product_list")),
body: SafeArea(
child: _buildView(),
),
);
},
);
}
运行
代码
https://github.com/ducafecat/flutter_develop_tips/tree/main/flutter_application_get_it
小结
在项目中使用 get_it 可以单例工具类、懒加载业务类、工厂方式实例不同商品、异步初始需要 await 的对象、全局管理用户Auth登录认证、样式切换、等配置信息,而不是用 GetxService 对象。
感谢阅读本文
如果我有什么错?请在评论中让我知道。我很乐意改进。
flutter 学习路径
- Flutter 基础篇1 - Dart 语言学习 https://ducafecat.com/course/dart-learn
- Flutter 基础篇2 - 快速上手
https://ducafecat.com/course/flutter-quickstart-learn - Flutter 实战1 - Getx Woo 电商APP
https://ducafecat.com/course/flutter-woo - Flutter 实战2 - 上架指南 Apple Store、Google Play https://ducafecat.com/course/flutter-upload-apple-google
- Flutter 基础篇3 - 仿微信朋友圈 https://ducafecat.com/course/flutter-wechat
- Flutter 实战3 - 腾讯 tim 即时通讯开发 https://ducafecat.com/course/flutter-tim
© 猫哥 ducafecat.com
end