Flutter SmartRefresher热重载或横竖屏切换触发控制器重复绑定错误如何解决
异常产生原因
- 核心触发逻辑是
pull_to_refresh库的内置校验:同一个RefreshController禁止同时绑定多个SmartRefresher实例,你遇到的场景刚好触发了这个校验规则。 - 具体场景原因:
- 你的
RefreshController存放在GetX控制器中,生命周期和页面Widget的生命周期不匹配。当你触发热重载、横竖屏切换时,页面Widget会重新构建,旧的SmartRefresher实例还没来得及释放和控制器的绑定关系,新构建的SmartRefresher又尝试绑定同一个控制器,就会抛出断言异常。 - 视图层用
Obx包裹了条件渲染逻辑:加载状态下返回进度指示器,非加载状态下返回SmartRefresher,每次加载状态切换都会导致SmartRefresher被销毁后重建,也会重复触发控制器绑定逻辑。
- 你的
修复方案
你可以按需选择以下任意一种方案:
- 方案1:快速修复,给
SmartRefresher添加唯一Key,强制框架在组件重构时自动解绑旧的控制器绑定关系,修改代码如下:
SmartRefresher( key: UniqueKey(), // 新增这行 controller: controller.refreshController, enablePullUp: true, onRefresh: ()=> controller.onRefresh(), onLoading: () => controller.onLoading(), // 其余原有参数不变 )
- 方案2:调整控制器存放位置,将
RefreshController改为在页面State中初始化,页面销毁时手动调用释放方法:
// 页面State类中定义 late RefreshController refreshController; @override void initState() { super.initState(); refreshController = RefreshController(initialRefresh: false); } @override void dispose() { refreshController.dispose(); super.dispose(); }
- 方案3:优化视图层结构,避免
SmartRefresher被频繁销毁重建,改用Stack叠加加载指示器,修改逻辑如下:
Widget build(BuildContext context) { return Obx(() { return Stack( children: [ SizedBox( height: MediaQuery.of(context).size.height, child: SmartRefresher( controller: controller.refreshController, enablePullUp: true, onRefresh: ()=> controller.onRefresh(), onLoading: () => controller.onLoading(), child: StaggeredGridView.countBuilder( // 原有列表参数不变 ), ), ), // 加载状态控制指示器显隐 if(controller.isLoading.value == true || controller.isLoadingSearch.value == true) const Center(child: CircularProgressIndicator(color: Colors.black,)) ], ); }); }
内容的提问来源于stack exchange,提问作者Osama Mohammed
相关产品推荐
相关产品推荐

