我的应用中有一个简单的帖子模块,在帖子概览和帖子详情页上显示 "心"。在这两个页面上,用户可以 "心动 "一个帖子,这样做会将用户ID写回火库文档,并增加整体的心动计数器。
问题是,如果帖子在概览页上被心动,然后用户导航到详情页,新的计数和新的 "心动 "状态没有显示。似乎是导航到下一个页面后没有新设置状态。变量似乎是正确的,因为我用各种打印语句测试过。一旦我再次手动点选 "心",就会显示出正确的计数器和 "心 "的状态。
因此,我如何才能在导航仪.推送命令后强制设置状态?
从第一页开始导航。
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => new PostPage(postData: widget.postData)));
}, [...] )
Hearts组件--单独的.dart文件,被包含在post overview和post detail页面中。
class _PostStatsState extends State<PostStats> {
var _heartsIcon = Icons.favorite;
dynamic _hearts = -1;
dynamic _setState = false;
Future<String> getUserId() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString('userId');
}
@override
Widget build(BuildContext context) {
final PostModel postData = InheritedPostModel.of(context).postData;
void setHeartsIcon()async{
final userId = await getUserId();
if (postData.heartedBy.contains(userId)) {
_heartsIcon = Icons.favorite;
}
else {
_heartsIcon = Icons.favorite_border;
}
}
_hearts = widget.hearts;
setHeartsIcon();
print("!Set $_hearts $_heartsIcon"); // correct number and icon are printed
[...]
小部件组件。 小部件组件:/不显示与上面打印的相同的数字和图标。
[...]
_showStat(
_heartsIcon,
_hearts,
Colors.red[300],
_heartOrUnheart
),
[...]
小工具
Widget _showStat(IconData icon, int number,Color color, Function buttonAction) {
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 2.0),
child: IconButton(icon: Icon(icon), color: color, onPressed: buttonAction,
enableFeedback: true,),
),
Text(number.toString()),
],
);
}
我找来找去,花了太多的时间来解决这个问题,却没有任何收获。希望有人有一个简单的解决方案。
你可以在initState中设置数据,但你使用的是InheritedWidgets,所以你应该像这样在didChangeDependencies中设置。
class _PostStatsState extends State<PostStats> {
var _heartsIcon = Icons.favorite;
dynamic _hearts = -1;
dynamic _setState = false;
Future<String> getUserId() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString('userId');
}
void setHeartsIcon(PostModel postData)async{
final userId = await getUserId();
if (postData.heartedBy.contains(userId)) {
_heartsIcon = Icons.favorite;
}
else {
_heartsIcon = Icons.favorite_border;
}
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
final PostModel postData = InheritedPostModel.of(context).postData;
_hearts = widget.hearts;
setHeartsIcon(postData);
print("!Set $_hearts $_heartsIcon");
}
@override
Widget build(BuildContext context) {
[....]
尽量保持你的构建方法的干净。
如果你没有使用 Inhertied widget,你可以采用另一种方法,将前一个页面的数据传递到这个页面,并在 initState 中设置它。
@override
Widget build(BuildContext context) {
return FutureBuilder<void>(
future: _setHeartsIcon(), // async work
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return _showStats();
}
else {
// Otherwise, display a loading indicator.
return _showStats();
}
},
);
}
这可能不是最干净的代码,但它确保在所有数据被加载后,_showStats()会被再次调用。由于数据只从SharedPreferences异步拉取,这似乎是一个毫秒的问题,在UI上并不可见。