我正在为我的应用创建新闻提要,当我向下滚动时,将从 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
, andScrollViews
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 anAutomaticKeepAliveClientMixin
. This mixin makes the children ask their parent to keep them alive even when off-screen, which will solve our problem. So:
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;
}
https://stackoverflow.com/questions/51536756/
相关文章:
android - Flutter中如何解析json数据并显示在Listview中?
firebase - 如何在 Flutter 中设置不同的 firebase 环境
firebase - 如何使用 Firebase 在 Flutter 中进行电话身份验证?
firebase - flutter |如何将数据添加到 Firestore 中的现有文档
android - Flutter - 多个手势,无需抬起手指
dart - 如何删除 RadioListTile 上的内部填充,以便可以连续使用 3 个 Radi
android - 如何在 Flutter 中禁用发布版本中的所有日志 [debugPrint()]