写点什么

使用 GetX 构建更优雅的 Flutter 页面结构

作者:岛上码农
  • 2022 年 6 月 22 日
  • 本文字数:2189 字

    阅读完需:约 7 分钟

使用GetX构建更优雅的Flutter页面结构

前言

App 的大部分页面都会涉及到数据加载、错误、无数据和正常几个状态,在一开始的时候我们可能数据获取的状态枚举用 if...else 或者 switch 来显示不同的 Widget,这种方式会显得代码很丑陋,譬如下面这样的代码:


if (PersonalController.to.loadingStatus == LoadingStatus.loading) {  return Center(    child: Text('加载中...'),  );}if (PersonalController.to.loadingStatus == LoadingStatus.failed) {  return Center(    child: Text('请求失败'),  );}// 正常状态PersonalEntity personalProfile = PersonalController.to.personalProfile;return Stack(  ...);
复制代码


这种情况实在是不够优雅,在 GetX 中提供了一种 StateMixin 的方式来解决这个问题。

StateMixin

StateMixin 是 GetX 定义的一个 mixin,可以在状态数据中混入页面数据加载状态,包括了如下状态:


  • RxStatus.loading():加载中;

  • RxStatus.success():加载成功;

  • RxStatus.error([String? message]):加载失败,可以携带一个错误信息 message

  • RxStatus.empty():无数据。


StateMixin 的用法如下:


class XXXController extends GetxController    with StateMixin<T>  {}
复制代码


其中 T 为实际的状态类,比如我们之前一篇 PersonalEntity,可以定义为:


class PersonalMixinController extends GetxController    with StateMixin<PersonalEntity>  {}
复制代码


然后StateMixin 提供了一个 change 方法用于传递状态数据和状态给页面。


void change(T? newState, {RxStatus? status})
复制代码


其中 newState 是新的状态数据,status 就是上面我们说的 4 种状态。这个方法会通知 Widget 刷新。

GetView

GetX 提供了一个快捷的 Widget 用来访问容器中的 controller,即 GetViewGetView是一个继承 StatelessWidget的抽象类,实现很简单,只是定义了一个获取 controllerget 属性。


abstract class GetView<T> extends StatelessWidget {  const GetView({Key? key}) : super(key: key);
final String? tag = null;
T get controller => GetInstance().find<T>(tag: tag)!;
@override Widget build(BuildContext context);}
复制代码


通过继承 GetView,就可以直接使用controller.obx构建界面,而 controller.obx 最大的特点是针对 RxStatus 的 4 个状态分别定义了四个属性:


Widget obx(  NotifierBuilder<T?> widget, {  Widget Function(String? error)? onError,  Widget? onLoading,  Widget? onEmpty,})
复制代码


  • NotifierBuilder<T?> widget:实际就是一个携带状态变量,返回正常状态界面的函数,NotifierBuilder<T?>的定义如下。通过这个方法可以使用状态变量构建正常界面。


typedef NotifierBuilder<T> = Widget Function(T state);
复制代码


  • onError:错误时对应的 Widget构建函数,可以使用错误信息 error

  • onLoading:加载时对应的 Widget

  • onEmpty:数据为空时的 Widget



通过这种方式可以自动根据 change方法指定的 RxStatus 来构建不同状态的 UI 界面,从而避免了丑陋的 if...elseswitch 语句。例如我们的个人主页,可以按下面的方式来写,是不是感觉更清晰和清爽了?


class PersonalHomePageMixin extends GetView<PersonalMixinController> {  PersonalHomePageMixin({Key? key}) : super(key: key);  @override  Widget build(BuildContext context) {    return controller.obx(      (personalEntity) => _PersonalHomePage(personalProfile: personalEntity!),      onLoading: Center(        child: CircularProgressIndicator(),      ),      onError: (error) => Center(        child: Text(error!),      ),      onEmpty: Center(        child: Text('暂无数据'),      ),    );  }}
复制代码


对应的 PersonalMixinController 的代码如下:


class PersonalMixinController extends GetxController    with StateMixin<PersonalEntity> {  final String userId;  PersonalMixinController({required this.userId});
@override void onReady() { getPersonalProfile(userId); super.onReady(); }
void getPersonalProfile(String userId) async { change(null, status: RxStatus.loading()); var personalProfile = await JuejinService().getPersonalProfile(userId); if (personalProfile != null) { change(personalProfile, status: RxStatus.success()); } else { change(null, status: RxStatus.error('获取个人信息失败')); } }}
复制代码

Controller 的构建

从 GetView 的源码可以看到,Controller 是从容器中获取的,这就需要使用 GetX 的容器,在使用 Controller 前注册到 GetX 容器中。


Get.lazyPut<PersonalMixinController>(  () => PersonalMixinController(userId: '70787819648695'),);
复制代码

总结

本篇介绍了使用GetXStateMixin方式构建更优雅的页面结构,通过controller.obx 的参数配置不同状态对应不同的组件。可以根据 RxStatus 状态自动切换组件,而无需写丑陋的 if...elseswitch 语句。当然,使用这种方式的前提是需要在 GetX 的容器中构建 controller 对象,本篇源码已上传至:GetX 状态管理源码。实际上使用容器能够带来其他的好处,典型的应用就是依赖注入(Dependency Injection,简称 DI),接下来我们会使用两篇来介绍依赖注入的概念和具体应用。


发布于: 刚刚阅读数: 3
用户头像

岛上码农

关注

用代码连接孤岛,公众号@岛上码农 2022.03.03 加入

从南漂到北,从北漂到南的业余码农

评论

发布
暂无评论
使用GetX构建更优雅的Flutter页面结构_flutter_岛上码农_InfoQ写作社区