DEBUG HELP:Flutter StatefulWidget在滚出视图后不保持状态

时间:2018-04-05 05:38:29

标签: scroll persistence state flutter

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

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

PlaceWidget对象基本上构建并返回ListTile;它唯一的附加任务是跟踪favorited状态并相应地构建ListTile的UI。

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

  • main.dart代表整个应用,
  • places.dart用于http请求

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

从表面上看,当滚动出视图时,看起来好像丢失了对象的状态,但是一些调试日志记录告诉我。

假设我最喜欢 Oto Sushi 然后在屏幕外滚动但保留指向状态对象的指针,对象的favorited状态仍为true。然而,对象本身(类_PlaceWidgetState)被报告为defunct, not mounted 我无法再与该对象进行交互。如果我再次点击 Oto Sushi ,它会创建一个新的状态对象,并将该对象的favorited状态设置为true,就像之前一样。

只要我不在屏幕外滚动 Oto Sushi ,我就可以不受欢迎,而且行为正常。

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

1 个答案:

答案 0 :(得分:2)

因此,除了架构讨论之外,问题的原因在于如何构建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成员,而不是这样做。另外,请确保仅在State小部件内初始化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小部件。