我正在玩一个简单的应用来学习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 ,我就可以不受欢迎,而且行为正常。
我设法找到TextInputField
和ExpansionTile
的类似问题(例如this question),但我不知道如何将这些问题的解决方案转换为此问题。
答案 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
小部件。