Reputation: 31
This is the how I fetch the posts in postList from firebase firestore, I need a function that works to get more posts on scroll. This next set of posts have to start after the last post that is displayed in this initial list and add to this list as the user scrolls as long as there are posts in the firestore.
class _FeedScreenState extends State<FeedScreen> {
List<Post> _posts = [];
ScrollController _controller = ScrollController();
@override
void initState() {
super.initState();
_setupFeed();
_controller.addListener(_scrollListener);
}
_scrollListener() {
setState(() {
if (_controller.position.atEdge) {
if (_controller.position.pixels == 0) {
} else {
_getMore();
}
}
});
}
_setupFeed() async {
List<Post> posts = await DatabaseService.getFeedPosts(widget.currentUserId);
setState(() {
_posts = posts;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'New List',
style: TextStyle(
color: Colors.black,
fontSize: 35.0,
),
),
),
body: RefreshIndicator(
onRefresh: () => _setupFeed(),
child: ListView.builder(
controller: _controller,
itemCount: _posts.length,
itemBuilder: (BuildContext context, int index) {
Post post = _posts[index];
return FutureBuilder(
future: DatabaseService.getUserWithId(post.authorId),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return SizedBox.shrink();
}
User author = snapshot.data;
return PostView(
currentUserId: widget.currentUserId,
post: post,
author: author,
);
},
);
},
),
),
);
}
}
this is how i fetch the list of posts
static Future<List<Post>> getFeedPosts(String userId) async {
QuerySnapshot feedSnapshot = await feedsRef
.document(userId)
.collection('userFeed')
.orderBy('timestamp', descending: true)
.limit(30)
.getDocuments();
List<Post> posts =
feedSnapshot.documents.map((doc) => Post.fromDoc(doc)).toList();
return posts;
}
Upvotes: 3
Views: 262
Reputation: 1948
I think doing this will solve your issue:
You have to edit your getFeedPosts to collect your posts starting at a given index:
I'm not familiar to FireStore, I've found the startAt()
method on docs
EDIT: I've misunderstood a Firestore concept, so I've change startAt()
to startAfter()
following Francisco Javier Snchez advice
static Future<List<Post>> getFeedPosts(String userId, TimeStamp start) async {
QuerySnapshot feedSnapshot = await feedsRef
.document(userId)
.collection('userFeed')
.orderBy('timestamp', descending: true)
.startAfter(start)
.limit(30)
.getDocuments();
List<Post> posts =
feedSnapshot.documents.map((doc) => Post.fromDoc(doc)).toList();
return posts;
}
Now you can query it like this:
_getMore() async {
// You have to give the timestamp of the last post here
// Change this line by the right way...
List<Post> posts = await DatabaseService.getFeedPosts(widget.currentUserId, _posts[_posts.length - 1].timestamp);
setState(() {
// Do += instead of =, += will add fetched posts to the current list, = will overwrite the whole list
_posts += posts;
});
}
Hope this will help!
Upvotes: 2
Reputation: 1003
na2axl answer was almost right. I will add here an explanation and example of how to use startAfter()
If you check the documentation on pagination, you will see that you need to use startAfter()
referencing whatever filter you used. In your case you are ordering using timestamp
so your next query should look like this:
static Future<List<Post>> getNextFeedPosts(String userId, TimeStamp timestamp) async {
QuerySnapshot feedSnapshot = await feedsRef
.document(userId)
.collection('userFeed')
.orderBy('timestamp', descending: true)
//Here you need to let Firebase know which is the last document you fetched
//using its timesTamp
.startAfter(timestamp)
.limit(30)
.getDocuments();
List<Post> posts =
feedSnapshot.documents.map((doc) => Post.fromDoc(doc)).toList();
return posts;
}
This means that your next query will still be ordered by a timestamp
but the first document retrieved will be after the timestamp
on startAfter
I hope this helps, however, you can check the documentation as there are other examples!
Upvotes: 2