spo*_*oss 7 dart firebase flutter google-cloud-firestore
我正在为我的应用创建一个新闻提要,当我向下滚动时,数据是从 Firestore 获取的。一旦我向上滚动,列表视图就会直接捕捉到最顶部,跳过中间的所有其他项目。如果我使用静态数据加载列表视图,列表视图工作正常,但是当我从 Firestore 提取数据时,问题再次出现。我不确定是什么导致了这种行为。
这是我的代码
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]),);
});
},
);
Run Code Online (Sandbox Code Playgroud)
问题原因:
\n\n\n\n\n\n
ListView,并且ScrollViews一般来说,倾向于处理当前在屏幕上不可见的子项。当我们尝试滚动回子项时,子项将从头开始重新初始化。但在这种情况下,我们的孩子是一个 FutureBuilder;重新初始化它会再次创建一个进度指示器,仅持续一秒钟,然后再次创建页面。这会混淆滚动机制,让我们陷入不确定的境地。
解决方案:
\n\n\n\n\n解决此问题的一种方法是确保进度指示器与页面大小完全相同,但在大多数情况下,这不太实用。所以,我们会采取一种效率较低的方法,但可以解决我们的问题;我们将阻止 ListView 处理子项。为了做到这一点,我们需要用
\nFutureBuilder一个AutomaticKeepAliveClientMixin. 这种混合使孩子们要求父母让他们即使在屏幕外也能活下去,这将解决我们的问题。所以:
class KeepAliveFutureBuilder extends StatefulWidget {\n\n final Future future;\n final AsyncWidgetBuilder builder;\n\n KeepAliveFutureBuilder({\n this.future,\n this.builder\n });\n\n @override\n _KeepAliveFutureBuilderState createState() => _KeepAliveFutureBuilderState();\n}\n\nclass _KeepAliveFutureBuilderState extends State<KeepAliveFutureBuilder> with AutomaticKeepAliveClientMixin {\n @override\n Widget build(BuildContext context) {\n return FutureBuilder(\n future: widget.future,\n builder: widget.builder,\n );\n }\n\n @override\n bool get wantKeepAlive => true;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n小智 6
这个问题有2个解决方案:
解决方案1:(如果ListView的高度是动态的)
ListView包裹起来SingleChildScrollViewphysics: const NeverScrollableScrollPhysics()如前所述设置ListView 的属性shrinkWrap: true以避免渲染问题或者
解决方案2:(如果ListView的高度已知或可预测)
cacheExtent:为 ListView 的高度 - 它是一个double值。cacheExtent: 200.0刚刚在使用 Flutter 1.17.3 时遇到了同样的问题。基于@Ashton-Thomas 的评论:Flutter ListView Jumps To Top我补充说:
cacheExtent: estimatedCellHeight * numberOfItems,
Run Code Online (Sandbox Code Playgroud)
到我的ListView构造函数,问题就消失了。它也大大提高了整个列表的响应能力。
注意:我的列表中只有大约 50 个项目,所以cacheExtent并不是很高。如果您有数百/数千个项目,则可能需要进行调整。
| 归档时间: |
|
| 查看次数: |
3481 次 |
| 最近记录: |