Flutter调用setState后UI未更新,RefreshIndicator刷新列表无变化
问题根因
你遇到的UI不更新是两个核心原因共同导致的:
TaskData作为ChangeNotifier子类,修改tasks属性后没有调用notifyListeners(),Consumer无法收到状态更新通知,自然不会触发UI重绘- 你在
FutureBuilder的构建逻辑中直接给taskData.tasks赋值,每次页面重绘时(包括你调用setState后),FutureBuilder都会拿第一次初始化的旧请求结果覆盖你刷新拿到的新数据,相当于刷新逻辑白跑了
修复步骤
1. 调整TaskData类的属性定义
给tasks增加setter逻辑,赋值后主动发送状态更新通知:
class TaskData extends ChangeNotifier { List<TaskDto> _tasks = []; // 只对外暴露可读的列表 List<TaskDto> get tasks => _tasks; set tasks(List<TaskDto> newTasks) { _tasks = newTasks; // 通知所有监听该状态的组件重绘 notifyListeners(); } }
2. 调整页面代码逻辑
移除FutureBuilder中重复赋值的逻辑,不需要用setState触发更新,调整后参考代码:
@override void initState() { super.initState(); taskListFuture= TaskService().getTasks(); } @override Widget build(BuildContext context) { return Consumer<TaskData>(builder: (context, taskData, child) { return FutureBuilder( future: taskListFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { // 这里返回加载中组件 return const Center(child: CircularProgressIndicator()); } if (snapshot.hasError || snapshot.data == null) { // 这里返回加载失败组件 return const Center(child: Text("加载任务失败")); } // 首次加载完成后给taskData赋值一次即可,不要每次重绘都赋值 if (taskData.tasks.isEmpty) { taskData.tasks = (snapshot.data as ApiResponseModel).responseBody; } return RefreshIndicator( onRefresh: () async { var responseModel = await TaskService().getTasks(); if (responseModel?.isSuccessStatusCode == true) { // 直接更新状态即可,内部会自动通知UI刷新,不需要setState taskData.tasks = responseModel.responseBody; } }, child: ListView.builder( // 列表项直接使用taskData.tasks渲染即可 itemCount: taskData.tasks.length, // ... 其余列表逻辑 ), ); } ); }); }
可选优化建议
你已经使用了Provider做状态管理,完全可以把网络请求逻辑放到TaskData内部维护,不需要在页面层混合使用FutureBuilder处理加载逻辑,代码可维护性会更高,也能避免出现状态不同步的问题。
内容的提问来源于stack exchange,提问作者steve
相关产品推荐
相关产品推荐

