【Flutter】Getx设计模式及Provider、Repository、Controller、View等

news2024/11/17 22:44:29

本文基于Getx 4,x 本本

1、引入

再次接触到Flutter项目,社区俨然很完善和活跃。pubs.dev 寻找状态管理的时候看到很熟悉的Getx时间,俨然发现Getx的版本已到是4.x版本,看到Getx的功能已经非常强大了,庞大的API俨然成为一种开发框架,关于API不是本文介绍的目的。我们就去繁从简,看看从框架层次,作者想传递给我们什么开发思想呢。

2、官方示例

2.1示例结构

Get示例图

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()));
  }
}
```

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1574561.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通俗易懂的理解 ADC(2)

理解什么是ADC 文章目录 1、通俗理解什么是ADC 2、什么是ADC 3、ADC的采样率 4、采样位数 5、采样精度 ADC实际没有这么的简单&#xff0c;深入了解需要去学各种寄存器之间如何协作&#xff0c;信号如何走通。这些概念在后面会有讲解。 1、通俗理解…

[mmu/cache]-MMU的地址翻译(Address translation)指令介绍

快速链接: 【精选】ARMv8/ARMv9架构入门到精通-[目录] &#x1f448;&#x1f448;&#x1f448; Address translation system instructions AT指令的语法格式&#xff1a; 有了上面的语法格式后&#xff0c;就非常好理解armv8的MMU提供了14条AT指令了&#xff1a; MMU的地址…

[mmu/cache]-ARMV8的cache的维护指令介绍

快速链接: 【精选】ARMv8/ARMv9架构入门到精通-[目录] &#x1f448;&#x1f448;&#x1f448; Armv8里定义的Cache的管理的操作有三种&#xff1a; 无效&#xff08;Invalidate&#xff09; 整个高速缓存或者某个高速缓存行。高速缓存上的数据会被丢弃。清除&#xff08;Cl…

#{} 和 ${}区别

1、参数是Integer类型时候没区别&#xff08;#是预编译SQL&#xff0c;$是即时SQL&#xff09; 2、当参数是String类型时&#xff0c;就会出错了 &#xff08;1&#xff09;这是$的报错信息&#xff0c;因为我们的参数admin并没有加引号所以不满足字符串条件 (2)正确的SQL &am…

FJSP:美洲狮优化算法(Puma Optimizar Algorithm ,POA)求解柔性作业车间调度问题(FJSP),提供MATLAB代码

一、柔性作业车间调度问题 柔性作业车间调度问题&#xff08;Flexible Job Shop Scheduling Problem&#xff0c;FJSP&#xff09;&#xff0c;是一种经典的组合优化问题。在FJSP问题中&#xff0c;有多个作业需要在多个机器上进行加工&#xff0c;每个作业由一系列工序组成&a…

用可视化案例讲Rust编程5.用泛型和特性实现自适配绘制和颜色设置

上一节我们讲了用泛型实现返回结果&#xff0c;这一节我们来讲讲在函数签名里面使用泛型来对输入参数进行自适配。 先看UML设计图&#xff1a; 好吧&#xff0c;看起来有点复杂&#xff0c;我们一个个来解释。 首先定义的是一个生成绘图元素需要的参数结构,并且定义个特性&am…

LeetCode-1483. 树节点的第 K 个祖先【树 深度优先搜索 广度优先搜索 设计 二分查找 动态规划】

LeetCode-1483. 树节点的第 K 个祖先【树 深度优先搜索 广度优先搜索 设计 二分查找 动态规划】 题目描述&#xff1a;解题思路一&#xff1a;暴力解法会超时&#xff01;【一级一级往上跳&#xff0c;效率太低】解题思路二&#xff1a;倍增&#xff0c;利用二进制运算&#xf…

Python可视化之pandas

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.解决坐标轴刻度负号乱码2.解决中文乱码问题3.折线图Series.plot()&DataFrame.plot()4.条形图5.箱线图6.区域面积图&#xff08;堆积折线图&#xff09;7.散点…

UNITY实战进阶-BatchRendererGroup+Jobs+Burst+RVO2+GPUAnimation 实现万人团战(一)

研究思路&#xff1a;GPUAnimation把动画放入GPU中处理&#xff0c;BatchRendererGroup进行动态批量渲染处理&#xff0c;JobsBurst进行多线程处理逻辑&#xff08;移动、攻击等&#xff09;&#xff0c;RVO2采用Jobs的寻路导航。 准备工作&#xff1a; Editor > Project S…

注意!今明两天广东等地仍有较强降雨

中央气象台监测显示 进入4月以来 我国江南、华南北部强降雨 接连而至 湖南、江西、浙江中南部 福建大部、广东中北部等地降雨量 较常年同期偏多1倍以上 上述地区部分国家观测站 日雨量突破4月历史极值 截至4月7日早晨 广东广州、惠州、清远 韶关、河源等地部分地区 …

填字母游戏【蓝桥杯】/博弈+dfs

填字母游戏 博弈dfs #include<iostream> #include<map> using namespace std; //要用map存储已经处理过的字符串不然会超时 map<string,int> m; //dfs返回的就是结果 int dfs(string s) {//剪枝if(m.find(s)!m.end()) return m[s];//找到LOL代表输了if(s.fi…

浅谈Redis和一些指令

浅浅谈一谈Redis的客户端 Redis客户端 Redis也是一个客户端/服务端结构的程序。 MySQL也是一个客户端/服务端结构的程序。 Redis的客户端也有多种形态 1.自带命令行客户端 redis-cli 2.图形化界面的客户端&#xff08;桌面程序&#xff0c;web程序&#xff09; 像这样的图形…

随机森林、AdaBoost 和 XGBoost 三者之间的主要区别

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 集成学习是一种强大的机器学习范式&#xff0c;它通过构建并结合多个学习器来提高预测性能。其中&#xff0c;随机森林、AdaBoost 和 XGBoost 是集成学习领域中著名且广泛应用的方法。尽管这些方法共享…

C++ | Leetcode C++题解之第12题整数转罗马数字

题目&#xff1a; 题解&#xff1a; const string thousands[] {"", "M", "MM", "MMM"}; const string hundreds[] {"", "C", "CC", "CCC", "CD", "D", "DC&qu…

绕过断言的LFI-Assertion101

总结 getwebshell : 发现疑似LFI的地方 → 测试..过滤 → 尝试断言绕过 → 远程加载反弹shell → getwebshell 提 权 思 路 : suid文件发现 → aria2c远程下载ssh私钥覆盖/root/.ssh → ssh公钥登录提权 准备工作 启动VPN 获取攻击机IP → 192.168.45.218 启动靶机 获取目标…

邮件服务器:Postfix

文章目录 邮件服务器的功能与工作原理电子邮件的问题Mail server与DNS 之间的关系邮件传输所需要的组件(MTA、MUA、MDA)以及相关协议用户收信时服务器端所提供的相关协议&#xff1a;MRA电子邮件的数据内容 使用Postfix与Dovecot部署邮件系统部署基础的电子邮件系统配置Postfix…

山海鲸智慧农业可视化:开启农业现代化高效管理新时代

随着科技的不断进步&#xff0c;农业现代化已成为当今社会发展的重要趋势。在这一背景下&#xff0c;山海鲸智慧农业可视化解决方案应运而生&#xff0c;为农业生产带来了革命性的变革。它通过创新的可视化技术&#xff0c;将农业生产过程中的各个环节进行高效整合&#xff0c;…

OSPF协议详解

静态缺点 1、中大型复杂网络----配置量大 2、不能实时收敛 动态-----可以实时收敛 IGP----内部网关路由协议 RIP OSPF EIGRP ISIS EGP----外部网关路由协议 BGP IGP &#xff08;选路佳 占用资源 收敛快&#xff09;----一个协议好需满足这三个 距离矢量 DV RIP…

Pandas分箱/离散化cut与qcut的区别

cut与qcut区别 1、pd.cut()2、pd.qcut()3、cut与qcut区别 Pandas提供了智能剪贴功能&#xff1a;pd.cut()与pd.qcut()&#xff0c;它们通常用于更方便直观地处理关系型或标签型数据&#xff0c;将数据进行分箱/离散化 1、pd.cut() 我们可以通过两种方式使用cut()函数&#xff…

C++的并发世界(七)——互斥锁

0.死锁的由来 假设有两个线程T1和T2&#xff0c;它们需要对两个互斥量mtx1和mtx2进行访问。而且需要按照以下顺序获取互斥量的所有权&#xff1a; -T1先获取mte1的所有权,再获取mt2的所有权。 -T2先获取 mtx2的所有权。再铁取 mtx1的所有权。 如果两个线程同时执行&#xff0c…