Flutter GetX:热重启后页面变量不更新,首次启动正常?
问题解决方法
核心问题分析
热重启后页面一直显示加载圈的原因主要有两个:
build方法重复触发数据请求:页面的build会在热重启时重新执行,每次执行都会调用getData(),把_isSuccess重置为false,即使后续会改为true,但重复的请求会导致UI一直停留在加载状态。GetBuilder与RxBool的搭配问题:你用了响应式的RxBool,却用需要手动调用update()的GetBuilder,热重启时可能出现手动更新不及时或关联失效的情况。
具体修复方案
方案1:避免在build中调用数据请求
build方法会被频繁触发(热重启、屏幕旋转、父组件重建等),绝对不能在这里调用getData()。把请求移到页面初始化逻辑中:
如果是StatefulWidget:
@override void initState() { super.initState(); // 页面渲染完成后只调用一次数据请求 WidgetsBinding.instance.addPostFrameCallback((_) { uiKitTableCtrl.getData(children); }); } @override Widget build(BuildContext context) { return GetBuilder<UiKitTableContoller>( init: uiKitTableCtrl, builder: (_) { return Scaffold( body: !uiKitTableCtrl.isSuccess.value ? const Center(child: CircularProgressIndicator()) : ListTreeView(...) ); } ); }
如果是StatelessWidget,可以用GetX的控制器生命周期:
在控制器中重写onInit(如果需要页面加载时自动请求数据):
class UiKitTableContoller extends GetxController { // ... 原有代码 @override void onInit() { super.onInit(); // 这里传入需要的headRows,或者通过其他方式传递参数 getData(yourHeadRows); } }
方案2:用Obx替代GetBuilder,利用响应式自动更新
既然已经用了RxBool,直接用Obx可以自动响应变量变化,无需手动调用update(),更可靠:
控制器代码(可简化):
class UiKitTableContoller extends GetxController { final TreeViewController treeController = TreeViewController(); final RxBool isSuccess = false.obs; void getData(List<TableRow> headRows) async { isSuccess.value = false; await Future.delayed(const Duration(seconds: 2)); // ... 你的数据处理逻辑 isSuccess.value = true; // 不需要调用update(),Obx会自动刷新UI } }
页面代码:
@override Widget build(BuildContext context) { // 同样要把getData移到初始化逻辑,避免重复调用 return Obx(() { return Scaffold( body: !uiKitTableCtrl.isSuccess.value ? const Center(child: CircularProgressIndicator()) : ListTreeView(...) ); }); }
方案3:添加加载标记,避免重复请求
如果必须保留现有结构,可以在控制器中添加一个标记,防止重复执行数据请求:
class UiKitTableContoller extends GetxController { final TreeViewController _controller = TreeViewController(); TreeViewController get treeController => _controller; final RxBool _isSuccess = false.obs; RxBool get isSuccess => _isSuccess; bool _hasLoaded = false; // 新增:标记是否已加载过数据 void getData(List<TableRow> headRows) async { if (_hasLoaded) return; // 已加载过直接返回 _isSuccess.value = false; await Future.delayed(const Duration(seconds: 2)); // ... 数据处理 _isSuccess.value = true; _hasLoaded = true; update(); } }
内容的提问来源于stack exchange,提问作者Claire
相关产品推荐
相关产品推荐

