【问题标题】:Flutter set state not updating my UI with new dataFlutter 设置状态未使用新数据更新我的 UI
【发布时间】:2021-09-28 08:30:46
【问题描述】:

我有一个 ListView.builder 小部件包裹在一个 RefreshIndicator 中,然后是一个 FutureBuilder。刷新不会更新我的列表,我必须关闭应用程序并再次打开它,但刷新代码与我的FutureBuilder 相同。

请在下面查看我的代码,当我阅读它时,我希望小部件树肯定会更新。

@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.done) {
              taskData.tasks = (snapshot.data as ApiResponseModel).responseBody;
              return RefreshIndicator(
                onRefresh: () async {
                  var responseModel = await TaskService().getTasks();
                  setState(() {
                    taskData.tasks = responseModel.responseBody;
                  });
                },
                child: ListView.builder(
...
...

如果需要更多代码,请告诉我,提前致谢!

积分

  • 我正在使用 StatefulWidget
  • 任务数据是一个扩展 ChangeNotifier 的类
  • 调试刷新时,我可以在列表中看到新数据,但 UI 没有更新

getTasks()

  Future<ApiResponseModel> getTasks() async {
    try {
      var _sharedPreferences = await SharedPreferences.getInstance();
      var userId = _sharedPreferences.getString(PreferencesModel.userId);

      var response = await http.get(
        Uri.parse("$apiBaseUrl/$_controllerRoute?userId=$userId"),
        headers: await authorizeHttpRequest(),
      );

      var jsonTaskDtos = jsonDecode(response.body);
      var taskDtos= List<TaskDto>.from(
          jsonTaskDtos.map((jsonTaskDto) => TaskDto.fromJson(jsonTaskDto)));
      return ApiResponseModel(
          responseBody: taskDtos,
          isSuccessStatusCode: isSuccessStatusCode(response.statusCode));
    } catch (e) {
      return null;
    }
  }

【问题讨论】:

  • TaskService().getTasks() 看起来怎么样?
  • @rckrd 我刚刚添加了它

标签: flutter flutter-layout


【解决方案1】:

这里的问题似乎是您正在更新一个不属于 StatefulWidget 状态的属性。

setState(() {
  taskData.tasks = responseModel.responseBody;
});

这设置了TaskData 的属性部分。 我的建议是只使用Consumer 并重构TaskService,以便它控制TaskData 或类似的列表。比如:

提供者

class TaskService extends ChangeNotifier {
  List<TaskData> _data;

  load() async {
    this.data = await _fetchData();
  }

  List<TaskData> get data => _data;

  set data(List<TaskData> data) {
    _data = data;
    notifyListeners();
  }
}

小部件

class MyTaskList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<TaskService>(builder: (context, service, child) {
      return RefreshIndicator(
          onRefresh: () {
            service.getTasks();
          },
          child: ListView.builder(
                   itemCount: service.data.length,
                   itemBuilder: (BuildContext context, int index) {
                     return MyTaskItem(data:service.data[index]);
                   },
                 ),
         ); 
    });
  }
}

并确保在 service.getTasks() 方法中调用 notifyListeners() 以使 Consumer 重建

【讨论】:

  • 感谢您的评论,我重构了 TaskData 以拥有一个初始化任务列表并调用 notifyListeners() 的方法,这意味着我不会对 API 进行额外的调用。我发现问题是我将 taskListFuture 作为变量传递给FutureBuilder,而不是调用方法本身。我这样做是因为 youtube 视频说这是最佳做法。再次感谢!
  • 太棒了!但是为什么你同时拥有ConsumerFutureBuilder? @史蒂夫
  • 我将 FutureBuilder 用于异步 API 调用和 Consumer,因此我可以访问小部件树中的 taskData。我是 Flutter 的新手,如果我遗漏了什么或做某事效率低下,请告诉我,我总是想做得更好!提前致谢。
  • 不需要FutureBuilderConsumer 将在 notifyListeners() 被调用时重建。因此,如果您确保在新数据可用并且您的小部件将更新时调用 notifyListeners()。您可以使用 StatelessWidget 来包装您的 Consumer。首次创建提供程序时加载数据ChangeNotifierProvider&lt;YourModel&gt;(create: (_) =&gt; YourModel()..load())
【解决方案2】:

我认为(如果我错了,有人会纠正我)问题是您使用的是FutureBuilder,一旦它构建完成,您需要刷新整个小部件以便 FutureBuilder 收听更改。我可以建议一个StreamBuilder 来监听数据模型/api/任何类型的数据流提供的任何更改。或者更好的是,您可以使用某种状态管理,例如 Provider,并使用 Provider 包中的 Consumer 来通知小部件可能发生的任何更改。

【讨论】:

  • 非常正确,我使用了刷新指示器,以便用户可以在需要时刷新数据。 TaskData 还扩展了 ChangeNotifier,我使用了Consumer 小部件,如图所示。当我将项目删除/添加到列表时,它会更新。只是刷新不会用新数据更新列表。
  • 当你热重启时,UI更新了?唯一的问题是当您使用RefreshIndicator 执行此操作时,对吗?
  • 我刚刚用我的应用程序和我的自定义 API 端点尝试了这个,工作正常。可以发一下TaskService().getTasks()的方法吗?
  • 我在问题中添加了getTasks(),谢谢GM
猜你喜欢
  • 2021-05-26
  • 1970-01-01
  • 2020-09-03
  • 1970-01-01
  • 2020-10-10
  • 2021-03-19
  • 1970-01-01
  • 2021-08-02
  • 1970-01-01
相关资源
最近更新 更多