调用 setState() 时 Flutter FutureBuilder 不更新

You*_*ang 4 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) {
...
Run Code Online (Sandbox Code Playgroud)

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

我制作了一个按钮来使用 imagepicker 更新个人资料图像。在 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;
      }
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

Can*_*000 6

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

Future当您更改(in )的定义时_userProfile,您期望未来会更新...但什么也没有发生...

原因是未来不会更新snapshot.hasError,也snapshot.hasData不会else……唯一改变的是ConnectionState.done

解决方案:

之后添加一个新条件if (snapshot.hasError)将包括ConnectionState.done. 然后当你setState时,它会正确重建

更多信息请参见这篇精彩的解释

如果您仍然遇到问题,请告诉我。