You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter调用setState后UI未更新,RefreshIndicator刷新列表无变化

问题根因

你遇到的UI不更新是两个核心原因共同导致的:

  1. TaskData作为ChangeNotifier子类,修改tasks属性后没有调用notifyListeners(),Consumer无法收到状态更新通知,自然不会触发UI重绘
  2. 你在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 08:45:05