当返回不同的小部件时,返回不同 StatefulWidgets 的方法不更新

Posted

技术标签:

【中文标题】当返回不同的小部件时,返回不同 StatefulWidgets 的方法不更新【英文标题】:Method returning different StatefulWidgets not updating when different widget is returned 【发布时间】:2019-10-19 01:49:28 【问题描述】:

我有一个基于枚举值返回两个有状态小部件之一的方法。但是,即使我可以通过调试器看到正在返回“正确”小部件,UI 也只显示第一个呈现的小部件。似乎状态对象以某种方式在小部件的不同实例之间共享,或者我错过了一些东西。

Widget _buildInfoCard(LoginStatus status) 
    switch(status) 
        case LoginStatus.LOGIN_FAILED:
            return InfoCard("Login failed, please check your username and password.");
        default:
            return InfoCard("Please login with your username and password");
    

我希望显示的信息卡的文本与返回的信息卡的文本相对应,但默认情况下始终存在。我已经单步执行了代码,返回了正确的小部件,之后没有返回默认小部件,所以应该显示,但没有。

编辑: _buildInfoCard 方法在流构建器内部被调用。

【问题讨论】:

您是否在应该进行切换后的任何地方调用了 setState? 这可能是由于滥用StatefulWidget造成的。要么你需要didUpdateWidget,要么你爱上了***.com/questions/50818770/… @RémiRousselet 我确实这样做了,谢谢分享。老实说,这些应该是无状态的小部件,我现在明白了。不过,我想了解为什么这不起作用。为什么要创建一个新的小部件实例,导致它从一个完全不同的小部件继承状态?它们不应该是内存中不同的对象,还是这里有某种我不明白的颤动魔法? 【参考方案1】:

您需要为StatefulWidget 的每个实例提供一个密钥,否则它们可能会共享状态,如下所示:

Widget _buildInfoCard(LoginStatus status) 
  switch (status) 
    case LoginStatus.LOGIN_FAILED:
      return InfoCard(
        key: ValueKey(status),
        message: "Login failed, please check your username and password.",
      );
    default:
      return InfoCard(
        key: ValueKey(status),
        message: "Please login with your username and password",
      );
  

关于我们为什么需要密钥的非常好的文章:https://medium.com/flutter/keys-what-are-they-good-for-13cb51742e7d

【讨论】:

UniqueKey 不是这里的解决方案。它使任何重建都会破坏小部件的状态。它适用于链接的文章,因为它们的做法不同。 为什么两个不同的对象会共享状态?在实例化时不是每个都创建自己的状态吗? 这篇文章很有帮助,对我来说都是全新的信息——谢谢。【参考方案2】:

对于遇到相同问题的任何人 - 请点击 Jordan Davies 提供的链接,然后在 YouTube 上观看 Flutter 101 的第 2 集以了解更多信息。

问题在于,当您构建小部件树时,Flutter 框架会将这些小部件转换为元素,然后使用这些元素来呈现 UI。

flutter 框架在构建元素树时,会查看每个小部件,并将小部件类型与树中给定位置的元素类型进行比较。如果类型相同,flutter 可能会重复使用该元素。

有状态的小部件有一个长期存在的状态对象,当一个新的添加到元素树时,它们可能不会被包装元素删除。在这种情况下,新返回的小部件可能会使用来自先前渲染的有状态小部件的现有状态对象。

解决方案正如 Jordan 建议的那样,使用键来防止这种情况发生,或者使用无状态小部件。有状态小部件上还有其他方法也可以工作,但 Jordan 的回答最能满足我的期望。

【讨论】:

以上是关于当返回不同的小部件时,返回不同 StatefulWidgets 的方法不更新的主要内容,如果未能解决你的问题,请参考以下文章

当用户使用返回键从任何其他页面返回页面时如何刷新页面?

Flutter 不会使用不同的参数重建相同的小部件

使用 bloc 更改屏幕

在 Flutter 中使用条件选择不同的小部件集

如何检测按下的鼠标何时进入不同框架中的小部件

如何通过单击放置在同一页面上的小部件来显示不同的小部件