Scroll 调试帮助:flatterstatefulwidget不';t在滚动出视图后保持状态
我正在玩一个简单的应用程序来学习颤振。这是UI的结构:Scroll 调试帮助:flatterstatefulwidget不';t在滚动出视图后保持状态,scroll,persistence,state,flutter,Scroll,Persistence,State,Flutter,我正在玩一个简单的应用程序来学习颤振。这是UI的结构: app--MaterialApp--HomeScreen(有状态) |-ListView—PlaceWidget(有状态) |-列表砖 PlaceWidget对象基本上构建并返回一个ListTile;它唯一的额外职责是跟踪偏好的状态,并相应地构建ListTile的UI 源代码是,包括两个文件: 整个应用程序的main.dart,以及 http请求的places.dart 这是应用程序的行为方式: 从表面上看,当滚动到视图之外时,对象
app--MaterialApp--HomeScreen(有状态)
|-ListView—PlaceWidget(有状态)
|-列表砖
PlaceWidget对象基本上构建并返回一个ListTile;它唯一的额外职责是跟踪偏好的
状态,并相应地构建ListTile的UI
源代码是,包括两个文件:
- 整个应用程序的
,以及main.dart
- http请求的
places.dart
从表面上看,当滚动到视图之外时,对象的状态似乎丢失了,但是调试日志告诉我情况并非如此 假设我最喜欢的Oto Sushi然后将其从屏幕上滚动,但保留一个指向state对象的指针,该对象的
最喜欢的
状态仍然是true
。但是,对象本身(属于类\u PlaceWidgetState
)被报告为已失效,未装入
我再也不能和那个物体互动了。如果我再次点击Oto Sushi,它将创建一个新的state对象,并像以前一样将该对象的favorited
状态设置为true
只要我不在屏幕外滚动Oto Sushi,我就可以不喜欢它,一切正常
我设法在TextInputField
和expansionfile
(例如)中找到了类似的问题,但我不知道如何将这些问题的解决方案转化为这个问题。因此,撇开架构讨论不谈,问题的原因在于如何构造状态
对象。通过将数据传递给构造函数,您可以确保每次重建小部件时,它们的状态都会重置
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> { ... }
现在,小部件不断被重建的原因是,在列表视图中,屏幕外的小部件可能会被破坏-它是为非常大的列表设计的。为了防止出现这种情况,您还可以使用小部件。它不在视图中时不会呈现,因此不存在,也没有要维护的状态。你需要自己维持这个状态。@GünterZöchbauer你能再澄清一点我应该如何做到这一点吗?当它卷回视图时,是否再次调用其build()
函数?我意识到我可以简单地在更高的范围内保留一个变量来跟踪状态,我只是想知道是否有“好的代码”标准解决方案。当然,build
将再次被调用<代码>构建
在可见时通常也会被调用。我已经有一段时间没有对此进行研究了,但是如果它失去了状态,initState
也应该在它变为可见时再次渲染时调用。谢谢!我在MyApp
范围内用一个静态变量编写了一个脏的解决方案,以跟踪状态并在build()
方法中检查状态;它现在工作正常了。如果你有关于如何干净地做这件事的建议,我将不胜感激。你可能会感兴趣。Redux还经常用于维护状态,通常与InheritedWidget一起使用。为了将来参考,如果像我这样愚蠢的人遇到这个问题,完整的解决方案包括:-在中本地跟踪状态\u PlaceWidgetState
,以及通过从继承的widget
中拉入上下文来检索每个widget的状态。在Jonah的建议中,我们通过调用inheritedWidget.of(context)
进一步更新\u isChecked
,然后访问/更新\u isChecked
应处于的状态
class _PlaceWidgetState extends State<PlaceWidget> {
bool _isChecked = false; // only store state in State
Widget build() {
final Place place = widget.place;
// build your stuff.
}
}