本文基于Getx 4,x 本本
1、引入
再次接触到Flutter
项目,社区俨然很完善和活跃。pubs.dev
寻找状态管理的时候看到很熟悉的Getx
时间,俨然发现Getx
的版本已到是4.x
版本,看到Getx
的功能已经非常强大了,庞大的API俨然成为一种开发框架,关于API
不是本文介绍的目的。我们就去繁从简,看看从框架层次,作者想传递给我们什么开发思想呢。
2、官方示例
2.1示例结构
2.2 目录结构
2.3 总结
移动端 或者前端很少去直接操作远程数据
, 故不存在类似Spring 中的DAO
, 此处示例中抽象出的Provider
我们可以理解为服务提供者即此处的网络请求Service
,亦或者DBService
的上层服务提供者。
provider
2.3.1 Repository
关于上述的Provider
层, 从2.1中我们看到了,还有一层Repository
,那我们就开始唠唠这个Repository
设计模式。 JJ
关于此处Repository
模式大概有以下几点。
- 简化业务层(
Controller
)的数据处理逻辑DTO
可能有人会说了,Provider层已经将
Json
转换成Model
了,那这里怎么提效呢。Model
能可能并不完全是前端展现的Entity
,比如Model
中含有JsonString
。
- 提高测试性
便于Mock
仓储对象,来模拟数据访问想过 - 数据隔离的作用
这个是我YY的,原始数据的immutable。
2.3.2 Controller
关于Controller
, 从2.1 中我们看到了GetxController
混淆的两个协议,主要是生命周期
的监听。此处GetxContorller
不展开讲。
2.3.3 View
getx
有个与之对应的GetView
, 可以帮我们注入
对应的Controller
。此处需要注意的是,如果该View有多个Controller管理,那还是采用Get.put
Get.lazyPut
, Get.creat
来注入实例。
2.3.4 Bindings
class HomeBindings extends Bindings {
void dependencies() {}
}
通过Get.LazyPut
来注入实例。依次为Provider. -> Reposity -> Contorller
, 需要注意的是如果在首页用到Binding
initialBinding, 需要实例话。
3、JJ的示例
看到这里就没必要在看下去了,自己可以造个轮子。这里只是为了记录一下。
3.1 Presentation
3.1.1 View
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:xun_dian_ft/global_widgets/tabbar/presentation/controller/tabbar_controller.dart';
import 'package:xun_dian_ft/pages/home/presentation/view/mine_view.dart';
import 'package:xun_dian_ft/pages/home/presentation/view/notice_View.dart';
import 'package:xun_dian_ft/pages/home/presentation/view/process_view.dart';
import 'package:xun_dian_ft/pages/home/presentation/view/wrok_view.dart';
/// @brief: 自定义底部导航栏视图
/// @desc: 因iOSer 故定义成和iOS类名
/// @date: 2024-04-05 19:27
/// @author: jeversonjee
class TabbarWidget extends GetView<TabbarController> {
final TextStyle normalTextStyle = const TextStyle(color: Colors.grey, fontWeight: FontWeight.w500, fontSize: 12);
final TextStyle highlightTextStyle = const TextStyle(color: Colors.red, fontWeight: FontWeight.w700, fontSize: 16);
final List<BottomNavigationBarItem> mBarItems = <BottomNavigationBarItem>[
BottomNavigationBarItem(
label: '工作中心',
icon: Image.asset(
'lib/res/images/tab_work.png',
),
activeIcon: Image.asset(
'lib/res/images/tab_work_selected.png',
)),
BottomNavigationBarItem(
label: '巡店进度',
icon: Image.asset(
'lib/res/images/tab_process.png',
),
activeIcon: Image.asset(
'lib/res/images/tab_process_selected.png',
)),
BottomNavigationBarItem(
label: '通知公告',
icon: Image.asset(
'lib/res/images/tab_notice.png',
),
activeIcon: Image.asset(
'lib/res/images/tab_notice_selected.png',
)),
BottomNavigationBarItem(
label: '我的信息',
icon: Image.asset(
'lib/res/images/tab_mine.png',
),
activeIcon: Image.asset(
'lib/res/images/tab_mine_selected.png',
))
];
TabbarWidget({super.key});
_renderTabbarItem(BuildContext context, TabbarController ctrl) {
return Obx(() => MediaQuery(
data: MediaQuery.of(context).copyWith(textScaler: const TextScaler.linear(2.0)),
child: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
showSelectedLabels: true,
showUnselectedLabels: true,
unselectedItemColor: Colors.grey,
selectedItemColor: Colors.blueAccent,
selectedLabelStyle: highlightTextStyle,
unselectedLabelStyle: normalTextStyle,
onTap: ctrl.updateTabIndex,
currentIndex: ctrl.tabIndex.value,
items: mBarItems,
),
));
}
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
bottomNavigationBar: _renderTabbarItem(context, controller),
body: Obx(() => IndexedStack(
index: controller.tabIndex.value,
children: [WorkView(), ProcessView(), NoticeView(), MineView()],
)),
));
}
}
3.1.2 Controller
import 'package:get/get.dart';
import 'package:xun_dian_ft/global_widgets/tabbar/data/module_permission_provider.dart';
import 'package:xun_dian_ft/global_widgets/tabbar/data/module_permission_reposity.dart';
class TabbarController extends GetxController {
TabbarController({required this.reposity});
final IModulePermisionReposity reposity;
var tabIndex = 0.obs;
void updateTabIndex(int currentIdx) {
tabIndex.value = currentIdx;
List<Module> values = Module.values;
reposity.getAccessPermissionBy(values[currentIdx]);
}
void onInit() {
}
void dispose() {
super.dispose();
}
}
3.2 Data
3.2.1 Provider
import 'package:get/get.dart';
import 'package:xun_dian_ft/core/network/base_provider.dart';
enum Module {
work(description: '工作中心', checkName: 'Android工作中心'),
process(description: '巡店进度', checkName: 'Android巡店进度'),
notice(description: '通知公告', checkName: 'Android通知公告'),
mine(description: '我的信息', checkName: 'Android我的信息');
const Module({required this.description, required this.checkName});
final String description;
final String checkName;
}
/// @desc: 关于Provider即为上层数据操作层面,个人认为和Service相似.可以理解为imuatbleSorceData
/// @date:2024-04-06
/// @author: jeversonjee
abstract class IModulePermissionProvider {
Future<bool> accessToThisModule(Module module);
}
class ModulePermissionProvider extends BaseProvider implements IModulePermissionProvider {
Future<bool> accessToThisModule(Module module) async {
/// TODO: 实现相应的网络查询接口
return Future(() => true);
}
}
3.2.2 Reposity
import 'package:xun_dian_ft/global_widgets/tabbar/data/module_permission_provider.dart';
abstract class IModulePermisionReposity {
Future<bool> getAccessPermissionBy(Module module);
}
class ModulePersionReposity implements IModulePermisionReposity {
ModulePersionReposity({required this.provider});
final IModulePermissionProvider provider;
Future<bool> getAccessPermissionBy(Module module) {
return provider.accessToThisModule(module);
}
}
```
### 3.2.3 Bindings
````dart
import 'package:get/get.dart';
import 'package:xun_dian_ft/global_widgets/tabbar/data/module_permission_provider.dart';
import 'package:xun_dian_ft/global_widgets/tabbar/data/module_permission_reposity.dart';
import 'package:xun_dian_ft/global_widgets/tabbar/presentation/controller/tabbar_controller.dart';
class ModulePermissionBinding implements Bindings {
void dependencies() {
Get.lazyPut<IModulePermissionProvider>(() => ModulePermissionProvider());
Get.lazyPut<IModulePermisionReposity>(() => ModulePersionReposity(provider: Get.find<IModulePermissionProvider>()));
Get.lazyPut<TabbarController>(() => TabbarController(reposity: Get.find()));
}
}
```