我已经在我的 flutter 应用程序中实现了一个分页方案,但我不确定它的性能是否友好,以及它是否可能在未来的生产中导致问题,所以我想就它获得建议。 这是我的实现
首先,我使用父小部件中的流提供程序获取数据。
class BuyerSellerPostsPage extends StatefulWidget {
@override
_BuyerSellerPostsPageState createState() => _BuyerSellerPostsPageState();
}
class _BuyerSellerPostsPageState extends State<BuyerSellerPostsPage> {
...some code here...
bool isAtBottom = false;
int postToDisplay=10;
@override
void initState() {
super.initState();
// Setup the listener.
_scrollController.addListener(() {
if (_scrollController.position.atEdge) {
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
setState(() {
isAtBottom=true;
postToDisplay+=10;
print('now true');
});
}else{
setState(() {
print('now false');
isAtBottom=false;
});
}
}
});
}
@override
void dispose(){
_scrollController.dispose();
super.dispose();
}
...some code here..
@override
Widget build(BuildContext context) {
Position coordinates=Provider.of<Position>(context);
...some code here...
body: SingleChildScrollView(
controller: _scrollController,
child: StreamProvider<List<SellerPost>>.value(
value: SellerDatabaseService(
currentLocation: new GeoPoint(coordinates.latitude, coordinates.longitude,)
,filters: _setFilters,
selectedCategory: _selectedCategory,
selectedTag: _selectedTag,
postsToDisplay: postToDisplay
).inRangeSellerPosts ,
...some code here...
);
}else{
return Container(
);
}
},
),
),
//post list
BSellerPostList(),
...some code here...
}
}
要显示的初始帖子是 10。 在我的 initstate 中,我对我的滚动控制器使用了一个监听器,这样当用户滚动到底部时,更多的项目(+10)会加载到屏幕上。
在我的流提供程序中,我将 postsToDisplay int 传递给我下面后端的流
Stream <List<SellerPost>> get inRangeSellerPosts {
try {
return sellerPostCollection
.where("expireTime" , isGreaterThan: DateTime.now())
.orderBy('expireTime',descending: true)
.snapshots()
.map(yieldSellerPosts);
} catch (e) {
print(e.toString());
return null;
}
}
List<SellerPost> yieldSellerPosts(QuerySnapshot snapshot) {
List<String> l = [];
print(snapshot.documents.length);
try {
return snapshot.documents.map((doc) {
return SellerPost(
...some code here...
);
}).take(postsToDisplay)
.toList();
} catch (e) {
print(e.toString());
return null;
}
}
我现在获取快照并使用列表中的 take 方法仅获取所需的数字(postsToDisplay)。 这种方法在我的调试模式下工作正常。我不确定它在生产中或使用大型数据集时会如何表现。有人可以仔细检查一下吗,我将不胜感激。
答案 0 :(得分:0)
我个人使用了之前类似问题中发布的 this 答案的修改版本。 我的实现和其他人的实现都有利有弊。 考虑到您可能只需要 10 个分页项目,他的方法导致您可能永远不需要使用文档的文档更改。另一方面,我的方法不适用于流。它使用 future 来查询文档快照以在您继续时更新列表。
这是示例代码
bool _isRequesting = false;
bool _isFinish = false;
final _scrollController = ScrollController();
List<DocumentSnapshot> _posts = [];
@override
void initState() {
_scrollController.addListener(() {
if (_scrollController.position.atEdge) {
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
setState(() {
requestNextPage();
});
}
}
});
requestNextPage();
super.initState();
}
void requestNextPage() async {
try{
if (!_isRequesting && !_isFinish) {
QuerySnapshot querySnapshot;
_isRequesting = true;
if (_posts.isEmpty) {
//check if _posts list is empty so that we may render the first list of 10 items.
querySnapshot = await Firestore.instance
.collection('sellerPost')
.limit(10)
.getDocuments();
} else {
//if _posts list is not empty it means we have already rendered the first 10 items so we start querying from where we left off to avoid repetition.
querySnapshot = await Firestore.instance
.collection('sellerPost')
.startAfterDocument(_posts[_posts.length - 1])
.limit(10)
.getDocuments();
}
if (querySnapshot != null) {
int oldSize = _posts.length;
_posts.addAll(querySnapshot.documents);
int newSize = _posts.length;
if (oldSize == newSize) {
_isFinish = true;
}
_isRequesting = false;
}else{
_isFinish = false;
_isRequesting = false;
}
}catch(e){
print(e.toString());
}
}
因此,在上面的代码中,我使用滚动控制器来检测用户何时使用分页项目(例如 10 个帖子)滚动到页面底部。此事件触发我的函数 requestNextPage();
请注意,在 inititState
上,我们还调用 requestNextPage();
来呈现最初的 10 个帖子。
所以现在,每次检测到滚动到底部时,都会添加 10 个额外的帖子
_posts