【发布时间】:2021-12-18 01:08:12
【问题描述】:
我有一个 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 为用户名,以此类推。
我制作了一个按钮来使用 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;
}
);
}
}
【问题讨论】:
-
使用
setState更新_userProfile不会触发重建,因为_userProfile是build内部的一个局部变量。它应该是_UserHeaderState类的成员。
标签: flutter flutter-futurebuilder