Flutter - GetX Helper 助你规范应用 tag

欢迎关注微信公众号:FSA全栈行动 👋

一、前言

项目从一开始就选择了 GetX 做为我们的状态管理方案,但是 GetXLogic 的理想使用是一个类型仅存在一个实例的方式,而同一类型不同物件的详情页,则需要我们通过 tag 的方式去解决。

在这种情况下,在各个子 Widget 中想要去获取相应的 logic,就需要到处写相同的 tag 或者直接传 logic 实例,十分恶心。

我见过解决这个问题的一个方案,核心逻辑是以 Map + List 的方式去存储 tag,通过 Logic 类型从 Map 获取 List,再直接获取 List 的最后一个数据,删除也是直接操作最后一个,但是这样是不可靠的。

比如打开并替换当前页这个场景,新页面会添加 tagList 中,被替换的页面会将这个 tag 移除,而在此时被替换页面的 logic 被移除,但是其对应的 tag 还在,且为 List 里的最后一个,然后新页面拿着这个旧的 tag 去获取 logic,就会出现 XXXController" not found. You need to call "Get.put(XXXController())" or "Get.lazyPut(()=>XXXController())" 的错误~

当然不同的小伙伴对 GetX 的使用有着不同的理解,也会导致各种各样的问题,如果你有遇到其它的使用场景问题,欢迎留言分享。

我自己也实现了一套方案,以页面为维度,安全且方便地获取其 logiclogicTag,并且规范使用方式。

github.com/LinXunFeng/...

二、集成

打开 pub.dev/packages/ge... ,复制最新版本。

getx_helper 添加到你的 pubspec.yaml 中,并执行 flutter pub get

yaml 复制代码
dependencies:
  getx_helper: latest_version

在需要使用的地方中导入 getx_helper

dart 复制代码
import 'package:getx_helper/getx_helper.dart';

三、插件

1、安装

打开 vscode 的扩展,搜索 GetX Helper 并安装

安装完成后,在 Flutter 项目下,目录右击的菜单中会多如下选项

2、使用

这里假设你会将所有的页面都存放在 feature 目录,结构如下

shell 复制代码
.
├── main.dart
└── feature

右击 feature 目录,在菜单中选择 GetX: Simple Page,输入 home 回车,即可快速创建一个简单页面

shell 复制代码
.
├── main.dart
└── feature
    └── home
        ├── header
        │   └── home_header.dart
        ├── logic
        │   └── home_logic.dart
        ├── page
        │   └── home_page.dart
        └── state
            └── home_state.dart

如果你想拆分 Widget,可按如下步骤:

  1. 先去到 home 目录自行创建一个 widget 目录
  2. 然后右击该 widget 目录,选择 GetX: Mixin Widget
  3. 输入 Widget名,如 home_body_view,回车

这样即可快速生成一个模板 Widget,你可以在该模板 Widget 里直接拿到 logiclogicTag

四、结构说明

此时的目录结构如下

shell 复制代码
.
├── main.dart
└── feature
    └── home
        ├── header
        │   └── home_header.dart
        ├── logic
        │   └── home_logic.dart
        ├── page
        │   └── home_page.dart
        ├── state
        │   └── home_state.dart
        └── widget
            └── home_body_view.dart

结构的分层说明如下

文件 作用
header 声明类型,定义枚举、视图刷新 ID,存放业务所需的常量数据等
logic 处理业务逻辑
page 页面结构,可直接拿到 logiclogicTag
state 数据存储,可通过 logic.state 进行访问
widget 拆分的子部件,可直接拿到 logiclogicTag

五、代码说明

header 文件中定义了两个 Mixin

dart 复制代码
typedef HomeLogicPutMixin<W extends StatefulWidget>
    = GetxLogicPutStateMixin<HomeLogic, W>;

typedef HomeLogicConsumerMixin<W extends StatefulWidget>
    = GetxLogicConsumerStateMixin<HomeLogic, W>;
  • PutMixin: page 使用,用于从页面根部提供 logicTag
  • ConsumerMixin: widget 使用,用于获取 logicTaglogic

page

dart 复制代码
class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => HomePageState();
}

class HomePageState extends State<HomePage> with HomeLogicPutMixin<HomePage> {
  @override
  HomeLogic initLogic() => HomeLogic();
  
  // @override
  // String? customLogicTag() {
  //   return "https://github.com/LinXunFeng/getx_helper";
  // }

  @override
  Widget buildBody(BuildContext context) {
    return GetBuilder<HomeLogic>(
      tag: logicTag,
      builder: (_) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('Home'),
            centerTitle: true,
          ),
          body: const HomeBodyView(),
        );
      },
    );
  }
}

步骤

  1. PutMixin 用于页面的 State 进行 with
  2. 重写 initLogic 方法返回 logic 实例
  3. 重写 buildBody 方法,该方法充当以前的 build 方法
  4. 如果你想自定义 logicTag 的值,可以重写 customLogicTag 方法

withPutMixin 后,可直接获取 logiclogicTag

initState

需要注意的是,如果你是在 initState 方法中去使用 logiclogicTag,则请先执行 super.initState(),如:

dart 复制代码
@override
void initState() {
  super.initState();

  debugPrint('logic -- $logic');
  debugPrint('state -- ${logic.state}');
  debugPrint('tag -- $logicTag');
}

keepAlive

如果你 withPutMixin,那 with AutomaticKeepAliveClientMixin 就不再适用,需要调整为使用 KeepAliveWidget 去包裹。

dart 复制代码
class HomePageState extends State<HomePage> with HomeLogicPutMixin<HomePage> {
  ...
  @override
  Widget buildBody(BuildContext context) {
    Widget resultWidget = GetBuilder<HomeLogic>(
      tag: logicTag,
      ...
    );
    resultWidget = KeepAliveWidget(
      child: resultWidget,
    );
    return resultWidget;
  }
}
dart 复制代码
import 'package:flutter/material.dart';

class KeepAliveWidget extends StatefulWidget {
  const KeepAliveWidget({
    super.key,
    required this.child,
  });

  final Widget child;

  @override
  State<KeepAliveWidget> createState() => _KeepAliveWidgetState();
}

class _KeepAliveWidgetState extends State<KeepAliveWidget>
    with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return widget.child;
  }
}

widget

dart 复制代码
class HomeBodyView extends StatefulWidget {
  const HomeBodyView({super.key});

  @override
  State<HomeBodyView> createState() => _HomeBodyViewState();
}

class _HomeBodyViewState extends State<HomeBodyView>
    with HomeLogicConsumerMixin<HomeBodyView> {
  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text('Home body'),
    );
  }
}

ConsumerMixin 用于 WidgetState 进行 with,在 withConsumerMixin 后,也可直接获取 logiclogicTag

PutMixin 一致,如果你是在 initState 方法中去使用,则请先执行 super.initState()

六、最后

手敲这些文件和代码确实会很复杂,但有了相应的插件,这些都变得极为简单,不仅统一了使用规范,还提高了工作效率。

开源不易,如果你也觉得这个库好用 (github.com/LinXunFeng/...),请不吝给个 Star 👍 ,并多多支持!

好了,以上介绍的是针对新页面的使用姿势,对于已有页面要如何使用,请等待下一篇~

如果文章对您有所帮助, 请不吝点击关注一下我的微信公众号:FSA全栈行动, 这将是对我最大的激励. 公众号不仅有 Flutter 技术,还有 AIAndroidiOSPython 等文章, 可能有你想要了解的技能知识点哦~

相关推荐
程序员老刘23 分钟前
Flutter 3.35 更新要点解析
flutter·ai编程·客户端
神弥悠2 小时前
记一次VSCode远程连接失败的解决过程:从报错到搞定的全过程
visual studio code
阅文作家助手开发团队_山神2 小时前
第一章: Mac Flutter Engine开发准备工作
前端·flutter
python_1363 小时前
web请求和响应
java·spring·github
EmmaGuo20154 小时前
flutter3.7.12版本设置TextField的contextMenuBuilder的文字颜色
前端·flutter
鹏多多.6 小时前
flutter-使用device_info_plus获取手机设备信息完整指南
android·前端·flutter·ios·数据分析·前端框架
一宿君6 小时前
Github 9 个惊艳的开源 NL2SQL 项目
sql·nlp·github
x10n98 小时前
GitHub宕机时的应急协作方案
github
来来走走11 小时前
Flutter开发 网络请求
android·flutter
深圳多奥智能一卡(码、脸)通系统1 天前
以下是对智能电梯控制系统功能及系统云端平台设计要点的详细分析,结合用户提供的梯控系统网络架构设计和系统软硬件组成,分点论述并补充关键要点:
github