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

相关推荐
不午睡的探索者1 小时前
告别性能瓶颈!Python 量化工程师,进击 C++ 高性能量化交易的“必修课”!
c++·github
光溯星河1 小时前
【实践手记】Git重写已提交代码历史信息
后端·github
独立开阀者_FwtCoder1 小时前
URL地址末尾加不加 "/" 有什么区别
前端·javascript·github
独立开阀者_FwtCoder1 小时前
Vue3 新特性:原来watch 也能“暂停”和“恢复”了!
前端·javascript·github
寻月隐君2 小时前
告别 Vec!掌握 Rust bytes 库,解锁零拷贝的真正威力
后端·rust·github
OLong2 小时前
2025年最强React插件,支持大量快捷操作
前端·react.js·visual studio code
Zender Han3 小时前
Flutter 进阶:实现带圆角的 CircularProgressIndicator
flutter
inhere5 小时前
gookit/goutil v0.7.0 新版本发布:模块调整与功能增强
开源·go·github
用户621024530926 小时前
React:当UI开发从「搬砖」变成「搭乐高」的魔法时刻!
github