调用 setState() 时 Flutter FutureBuilder 不更新

标签 flutter flutter-futurebuilder

我有一个 DataProvider 和一个 FutureBuilder。

class _UserHeaderState extends State<UserHeader> {

  @override
  Widget build(BuildContext context) {
    var _dataProvider = context.watch<DataProvider>();
    var _userProfile = _dataProvider.getUserProfile();

    return FutureBuilder<UserProfile>(
      future: _userProfile,
      builder: (context, snapshot) {
...

我的 DataProvider.photoURL 有配置文件 URL,DataProvider.updatePhotoURL() 更新它。 DataProvider.getUserProfile()返回UserProfile类,UserProfile.name为用户名等。

我制作了一个按钮来使用图像选择器更新个人资料图像。 在 onPressed 中,我包装了 DataProvider.updatePhotoURL();和 _userProfile = DataProvider.getUserProfile();使用 setState。

期望的输出是当用户从图像选择器中选择照片时,我的 CircleAvatar 应该立即显示新选择的照片。

实际输出 是 CircleAvatar 显示旧照片,直到我点击热重载或访问另一个页面并返回。

似乎 setState() 和 FutureBuilder 快照的组合搞砸了,但无法弄清楚如何修复它。

完整代码如下。 (不包括 DataProvider 和 UserProfile 类)

class UserHeader extends StatefulWidget {

  @override
  _UserHeaderState createState() => _UserHeaderState();
}

class _UserHeaderState extends State<UserHeader> {

  @override
  Widget build(BuildContext context) {
    var _dataProvider = context.watch<DataProvider>();
    var _userProfile = _dataProvider.getUserProfile();

    return FutureBuilder<UserProfile>(
      future: _userProfile,
      builder: (context, snapshot) {
        Widget body = Center(child: null);

        if (snapshot.hasError) {
          print(snapshot.error);
          body = Center(child: ErrorPage(context));
        } else if (!snapshot.hasData) {
          body = Center(child: CircularProgressIndicator());
        } else {
          body = Padding(
            padding: EdgeInsets.all(16),
            child: Row(
                children: [
                  CircleAvatar(
                    backgroundImage: NetworkImage(snapshot.data!.photoURL),
                    radius: 40,
                    child: Stack(
                        children: [
                          Align(
                            alignment: Alignment.bottomRight,
                            child: RawMaterialButton(
                              elevation: 1.0,
                              fillColor: Colors.grey[800],
                              child: Icon(Icons.add_a_photo_rounded, size: 16),
                              shape: CircleBorder(),
                              materialTapTargetSize: MaterialTapTargetSize
                                  .shrinkWrap,
                              padding: EdgeInsets.all(6),
                              constraints: BoxConstraints(minWidth: 0),
                              onPressed: () {
                                print('update photo button pressed');
                                setState(() {
                                  _dataProvider.updatePhotoURL();
                                  _userProfile = _dataProvider.getUserProfile();
                                });
                              },
                            ),
                          )
                        ]
                    ),
                  ),
                ],
              ),
          );
        }
        return body;
      }
    );
  }
}

最佳答案

我之前遇到过同样的问题...

当您更改 Future 的定义(在 _userProfile 中)时,您希望 future 更新...但什么也没有发生...

原因是 Future 不会更新 snapshot.hasErrorsnapshot.hasDataelse... 唯一的发生变化的是 ConnectionState.done

解决方案:

if (snapshot.hasError) 之后添加一个新条件,其中将包含 ConnectionState.done。然后当你设置状态时,它会正确重建

更多信息请参见 this很好的解释

如果您还有问题,请告诉我。

关于调用 setState() 时 Flutter FutureBuilder 不更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69828487/

相关文章:

flutter - 什么是 future ,我将如何使用它?

flutter - 向我的项目添加 flavor 后,我无法为 Web 初始化 Flutter

android - 运行flutter项目时配置根项目 'android'出现问题

Flutter:滚动到 ListView 中的小部件

Flutter - 如何将 future 传递给小部件而不执行它?

flutter - Flutter:第一次在第二页上传入的参数值为null

Flutter FadeIn/FadeOut 动画在一起

ios - 如何使用 xcode 12.4 创建未签名的 ipa 文件?无法安装 "Runner"?代码 : Code: -402620388

flutter - Flutter:应该只有[DropdownButton]值的一项

flutter - 错误状态在使用 FutureBuilder 和 Provider 的 Flutter 中没有元素