【问题标题】:Flutter Navigator.push -> second page does not refresh state with new valuesFlutter Navigator.push -> 第二页不使用新值刷新状态
【发布时间】:2020-05-03 05:58:36
【问题描述】:

我的应用中有一个简单的帖子模块,它在帖子概述和帖子详细信息页面上显示“心”。在这两个页面上,用户都可以“关注”帖子,这样做会将用户 ID 写回 Firestore 文档并增加整体关注计数器。

问题在于,如果帖子在概览页面上被关注,然后用户导航到详细信息页面,则不会显示新的计数和新的“关注”状态。导航到下一页后,似乎状态不是新设置的。变量似乎是正确的,因为我已经用各种打印语句进行了测试。一旦我再次手动点击心脏,就会显示正确的计数器和心脏状态。

如何在 navigator.push 命令之后强制设置状态?

从第一页导航:

GestureDetector(
      onTap: () {
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => new PostPage(postData: widget.postData)));
      }, [...] )

Hearts 组件 - 单独的 .dart 文件,包含在帖子概述和帖子详细信息页面中:

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
[...]

Widget 组件: // 显示的数字和图标与上面打印的不同

[...]

_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()),
      ],
    );
  }

我环顾四周,花了太多时间来解决这个问题,但没有运气。希望有人对此有一个简单的解决方案。

【问题讨论】:

    标签: flutter state navigator


    【解决方案1】:

    您可以在 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 小部件,则可以将前一页的数据传递到本页并将其设置为 initState。

    【讨论】:

    • 谢谢 - 但是它似乎仍然没有完全解决问题......现在我最初得到了正确的状态,但更新功能不再正常工作。我还尝试将 setHeartsIcon 移动到以前的类并传递值,但这仍然不能完全解决问题。问题似乎已经融入了 navigator.push 机制
    • 将您的 setHeartsIcon 移动到 InheritedWidgets 并从它们那里获取。
    • 再次感谢 - 我终于通过使用未来的构建器解决了它。所以我认为主要问题是获取首选项/ userId 是异步的,因此构建方法在变量更新之前运行。我发布了适合我的新代码小部件代码
    【解决方案2】:
      @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 上并不真正可见。

    【讨论】:

      猜你喜欢
      • 2021-04-30
      • 2020-11-28
      • 1970-01-01
      • 2021-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-25
      • 1970-01-01
      相关资源
      最近更新 更多