我有一个 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.hasError
、snapshot.hasData
或 else
... 唯一的发生变化的是 ConnectionState.done
解决方案:
在 if (snapshot.hasError)
之后添加一个新条件,其中将包含 ConnectionState.done
。然后当你设置状态时,它会正确重建
更多信息请参见 this很好的解释
如果您还有问题,请告诉我。
关于调用 setState() 时 Flutter FutureBuilder 不更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69828487/