前言
上一篇我们介绍了 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
真正的优势所在。
评论