猫哥课堂 ducafecat.com
开通 VIP 会员, 观看所有视频、附件、猫哥密友、猫哥 VIP 群

在 getx 中使用 get_it 管理依赖注入

视频

https://www.youtube.com/watch?v=NBog-RdZ1fQ

https://www.bilibili.com/video/BV1EG411X7zz/

前言

原文 https://ducafecat.com/blog/use-get_it-in-getx

上一节讲了 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()); } ...

完整代码详见 https://github.com/ducafecat/flutter_develop_tips/blob/main/flutter_application_get_it/lib/common/utils/wp_http.dart

全局注入 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() {} 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, ), ); }, ); }
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 学习路径


© 猫哥 ducafecat.com

end


Copyright 2024 ducafecat. All rights reserved.
微信: ducafecat, line: ducafecat,京ICP备2021009050号-3