前言
上一篇我们介绍了 GetX 的的简单状态管理 GetBuilder 的使用,本篇我们继续,来在状态管理中完成网络请求后更新界面。在我们介绍 Provider 的时候做了一个个人主页:使用 FutureProvider 搞定个人主页异步请求的状态管理,我们这一篇来对比一下 GetX 和 Provider 的差异。
状态代码
这里我们网络请求还是使用 Dio,原先的请求相关的代码我们直接复制过来了,源码可以在这里下载:GetX应用代码。在 VSCode 的编辑界面输入 getcontroller 代码模板指令(需要安装 GetX Snippets 扩展)来说输入状态管理代码。这里我们有两个状态属性,一个是网络请求状态枚举_loadingStatus,用于指示网络请求状态;另一个是掘金的个人信息_personalProfile。在构造方法中我们传递用户 id,来请求个人信息数据。可以看到,实际上的代码和计数器的基本上一样,也是更新状态对象最新值,使用 update 通知界面刷新。存在的差别在于我们引入了 GetxController 的一个生命周期函数 onReady 来进行网络请求。onReady 在 GetX 的说明如下:
Called 1 frame after onInit(). It is the perfect place to enter navigation events, like snackbar, dialogs, or a new route, or async request.在 onInit()之后的一帧调用,非常适合放置导航入口事件,例如 SnackBar,对话框、新的路由或异步请求。
关于 GetxController 的生命周期我们下一篇再具体介绍,目前我们知道 GetX 推荐在 onReady 进行网络请求即可。
enum LoadingStatus { loading, success, failed,}
class PersonalController extends GetxController { static PersonalController get to => Get.find(); final String userId; PersonalController({required this.userId});
@override void onReady() { getPersonalProfile(userId); super.onReady(); }
PersonalEntity? _personalProfile; get personalProfile => _personalProfile;
LoadingStatus _loadingStatus = LoadingStatus.loading; get loadingStatus => _loadingStatus;
void getPersonalProfile(String userId) async { _loadingStatus = LoadingStatus.loading; _personalProfile = await JuejinService.getPersonalProfile(userId); if (_personalProfile != null) { _loadingStatus = LoadingStatus.success; } else { _loadingStatus = LoadingStatus.failed; } update(); }}
复制代码
界面代码
界面代码我们不贴了,我们只来对比和 Provider 的差异部分。
// GetX 最外层class PersonalHomePageWrapper extends StatelessWidget { const PersonalHomePageWrapper({Key? key}) : super(key: key);
@override Widget build(BuildContext context) { return GetBuilder<PersonalController>( init: PersonalController(userId: '70787819648695'), builder: (controller) => _PersonalHomePage(), ); }}//Provider 最外层class PersonalHomePageWrapper extends StatelessWidget { const PersonalHomePageWrapper({Key? key}) : super(key: key);
@override Widget build(BuildContext context) { return FutureProvider<PersonalEntity?>( create: (context) => JuejinService.getPersonalProfile('70787819648695'), initialData: null, child: _PersonalHomePage(), ); }}
复制代码
// GetX 代码@override Widget build(BuildContext context) { 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( children: [ CustomScrollView( slivers: [ _getBannerWithAvatar(context, personalProfile), _getPersonalProfile(personalProfile), _getPersonalStatistic(personalProfile), ], ), //...}
// Provider 代码class _PersonalHomePage extends StatelessWidget { const _PersonalHomePage({Key? key}) : super(key: key);
@override Widget build(BuildContext context) { PersonalEntity? personalProfile = context.watch<PersonalEntity?>(); if (personalProfile == null) { return Center( child: Text('加载中...'), ); } return Stack( children: [ CustomScrollView( slivers: [ _getBannerWithAvatar(context, personalProfile), _getPersonalProfile(personalProfile), _getPersonalStatistic(personalProfile), ], ), //...}
复制代码
那么 GetX 的优势在哪里呢?我们来将个人主页的代码复制一份,但是不再使用 GetBuilder 了,然后从个人主页增加一个按钮,点击后路由到该页面(见下图,为了区分,我们换了一张背景图)。
这个时候,这个页面其实和上一个页面已经没有任何关系了,但是却依旧可以使用PersonalController.to.personalProfile访问到个人信息数据。部分代码如下所示:
class PersonalHomePageCopy extends StatelessWidget { const PersonalHomePageCopy({Key? key}) : super(key: key);
@override Widget build(BuildContext context) { PersonalEntity personalProfile = PersonalController.to.personalProfile; return Stack( children: [ CustomScrollView( slivers: [ _getBannerWithAvatar(context, personalProfile), _getPersonalProfile(personalProfile), _getPersonalStatistic(personalProfile), ], ), //...}
复制代码
这就使得状态数据的复用更加简洁了,只要状态对象被初始化过后,就可以在任何组件使用——不需要组件之间有任何的关联,比如不需要有共同的父级组件。
总结
本篇介绍了在GetX 的状态管理中进行异步请求刷新界面,并和使用Provider进行状态管理的代码。可以看到 GetX 具备如下特点:
异步请求和普通的状态管理没什么差别,方式相当简单;
从 Provider 迁移到 GetX 修改的代码量不多;
GetX 的状态共享方式更简单,无需组件之间有任何关联,只要状态对象被初始化了,就可以在任何组件访问。这才是 GetX 真正的优势所在。
评论