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 等文章, 可能有你想要了解的技能知识点哦~

相关推荐
YuePeng3 小时前
写了五年注解的低代码框架,2.0 决定让你连注解都不用写了
github·产品
小白ai3 小时前
从"能 ping 通吗"到"为什么上不了网"——我写了一个网络故障诊断引擎
github
徐小夕5 小时前
jitword 协同文档3.2发布:打造浏览器中最强word编辑器
前端·架构·github
齐翊7 小时前
分享一个在 Claude Code 里 [同时] 用多个 ApiKey 的方法
程序员·github·agent
A_Lonely_Cat7 小时前
记一次 GitHub 幽灵协作者大清洗:强制重写 Git 历史与穿透 CDN 缓存实践
git·github
极光技术熊1 天前
Spring AI 从入门到精通:构建你的 AI 开发知识体系
后端·github
用户39483951075531 天前
怎么让我的 Agent 真正"懂"我?——关于记忆、经验学习与预测的一些真实体验
github
远航_1 天前
git submodule
前端·后端·github
恋猫de小郭1 天前
Amper 正式转正 Kotlin Toolchain ,Gradle 未来何去何从
android·前端·flutter
fthux1 天前
如果你用 Mac,那你可能需要 Noti Shift
macos·开源·github