gpt4 book ai didi

firebase - Flutter ListView 跳转到顶部

转载 作者:IT老高 更新时间:2023-10-28 12:41:34 36 4
gpt4 key购买 nike

我正在为我的应用创建新闻提要,当我向下滚动时,将从 Firestore 获取数据。一旦我向上滚动, ListView 就会立即捕捉到最顶部,从而跳过中间的所有其他项目。如果我用静态数据加载 ListView ,它可以正常工作,但是当我从 Firestore 中提取数据时,问题再次出现。我不确定是什么导致了这种行为。

Video demonstrating the irregular scrolling behaviour

这是我的代码

return StreamBuilder(
stream: Firestore.instance.collection(Constants.NEWS_FEED_NODE)
.document("m9yyOjsPxV06BrxUtHdp").
collection(Constants.POSTS_NODE).orderBy("timestamp",descending: true).snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData)
return Center(child: CircularProgressIndicator(),);

if (snapshot.data.documents.length == 0)
return Container();
//after getting the post ids, we then make a call to FireStore again
//to retrieve the details of the individual posts
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (_, int index) {
return FeedItem2(feed: Feed.fireStore(
snapshot: snapshot.data.documents[index]),);
});
},
);

最佳答案

问题原因:

ListView, and ScrollViews in general, tend to dispose of the children that are not currently visible on the screen. When we try to scroll back to the child, the child is reinitialized from scratch. But in this case, our child is a FutureBuilder; re-initializing it creates a progress indicator again just for a part of a second, then creates the page once again. This confuses the scrolling mechanism, throwing us around in non-deterministic ways.

Solution :

One way to solve this is to make sure that the progress indicator has the exact same size of the page, but in most cases, that is not too practical. So, we will resort to a method that is less efficient, but that will solve our problems; we will prevent ListView from disposing of the children. In order to do that, we need to wrap each child — that is, each FutureBuilder, with an AutomaticKeepAliveClientMixin. This mixin makes the children ask their parent to keep them alive even when off-screen, which will solve our problem. So:

  1. 将代码中的 FutureBuilder 替换为 KeepAliveFutureBuilder。
  2. 创建 KeepAliveFutureBuilder 小部件:
class KeepAliveFutureBuilder extends StatefulWidget {

final Future future;
final AsyncWidgetBuilder builder;

KeepAliveFutureBuilder({
this.future,
this.builder
});

@override
_KeepAliveFutureBuilderState createState() => _KeepAliveFutureBuilderState();
}

class _KeepAliveFutureBuilderState extends State<KeepAliveFutureBuilder> with AutomaticKeepAliveClientMixin {
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: widget.future,
builder: widget.builder,
);
}

@override
bool get wantKeepAlive => true;
}
  • 这个小部件只是 FutureBuilder 的一个包装器。它是一个 StatefulWidget,其 State 使用 AutomaticKeepAliveClientMixin 扩展了 State 类。
  • 它实现了 wantKeppAlive getter,并使其简单地返回 true,以向 ListView 表示我们希望这个 child 保持事件状态。

关于firebase - Flutter ListView 跳转到顶部,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51536756/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com