调试帮助:Flutter StatefulWidget 在滚动出视图后不保持状态

DEBUG HELP: Flutter StatefulWidget doesn't maintain state(s) after scrolled out of view

我正在玩一个简单的应用程序来学习 Flutter。这是 UI:

的结构

app -- MaterialApp -- HomeScreen (stateful) |- ListView -- PlaceWidget (stateful) |- ListTile

PlaceWidget object 基本上构建和 returns 一个 ListTile;它唯一的额外职责是跟踪 favorited 状态并相应地构建 ListTile 的 UI。

源码为here,包括两个文件:

这是应用程序的行为方式:https://gfycat.com/FineBelovedLeafhopper


从表面上看,当滚出视图时 object 的状态似乎丢失了,但一些调试日志告诉我情况并非如此。

假设我最喜欢 Oto Sushi 然后滚动它 off-screen 但保留指向状态 object 的指针,object 的 favorited 状态仍将是 true。然而,object 本身(属于 class _PlaceWidgetState)据报道为 defunct, not mounted
我无法再与那个 object 互动。如果我再点击一次 Oto Sushi,它将创建一个新状态 object 并将 object 的 favorited 状态设置为 true 和以前一样。

只要我不滚动 Oto Sushi off-screen,我就可以取消收藏,一切正常。

我设法找到了 TextInputFieldExpansionTile 的类似问题(例如 ),但我不知道如何将这些问题的解决方案转化为这个问题。

因此,撇开体系结构讨论不谈,问题的原因在于您如何构建 State 对象。通过构造函数传递数据,您可以确保每次重建小部件时,它们的状态都会被重置。

 class PlaceWidget extends StatefulWidget {
  @override
  _PlaceWidgetState createState() {
    return new _PlaceWidgetState(place, false); // woops, always unchecked
  }

  final Place place;
  PlaceWidget(this.place, {Key key}) : super(key: key);
}

class _PlaceWidgetState extends State<PlaceWidget> { ... }

不要这样做,而是使用状态小部件中的 widget getter 来访问 place 成员。还要确保您仅在状态小部件内初始化 checked 状态 - 或者从此处的某些外部源获取它。

class _PlaceWidgetState extends State<PlaceWidget> {
  bool _isChecked = false; // only store state in State

  Widget build() {
   final Place place = widget.place;
   // build your stuff.
  }
}

现在您的小部件不断重建的原因是在 ListView 中,屏幕外的小部件可能会被销毁 - 它是为非常大的列表设计的。为防止这种情况,您还可以使用 KeepAlive 小部件。