Reputation: 130
I have a firestore collection for 'brews' . Cant find a way to paginate the list of Brews. you can find the whole code at (https://github.com/iamshaunjp/flutter-firebase/tree/lesson-27) if needed. Thanks..
class BrewList extends StatefulWidget {
@override
_BrewListState createState() => _BrewListState();
}
class _BrewListState extends State<BrewList> {
@override
Widget build(BuildContext context) {
final brews = Provider.of<List<Brew>>(context) ?? [];
return ListView.builder(
itemCount: brews.length,
itemBuilder: (context, index) {
return BrewTile(brew: brews[index]);
},
);
}
}
Upvotes: 0
Views: 369
Reputation: 2664
Okay sorry about delay in answer but this is what i think your function would look like this saves all your brews into a list as brews then you could map them to widgets.
Future<void> queryFirebase(String starting, String ending) async {
final List<Brew> brewsList = []; //this need to be intialized higher up not in this function
//if you intialized it in this function it will reset to empty every time you call the function
QuerySnapshot brewsSnapshot = await Firestore.instance
.collection('collection')
.where('name', isGreaterThanOrEqualTo: starting)
.where('name', isLessThanOrEqualTo: ending)
.orderBy('name')//this sorts your query if you want that
.getDocuments();
if (brewsSnapshot == null) {
return;
}
brewsSnapshot.documents.forEach(
(DocumentSnapshot brewsDocuments) => {
brewsList.add(
Brew(
sugars: brewsDocuments.data['sugars'],
name: brewsDocuments.data['name'],
strength: int.parse(
brewsDocuments.data['sugars'],
),
),
),
},
);
notifyListeners();
}
then the calls to the function would be something like
await queryFirebase('A', //name of last brew you want displayed initially)
await queryFirebase('//next brew after last one from last function', //name of last brew you want displayed )
await queryFirebase('//next brew after last one from last function', 'Z' )
Upvotes: 1
Reputation: 2664
Okay so I want to explain a little about whats going on here first 20 items load then NotificationListener
triggers every time we reach the bottom of the list until all the items are loaded then it turns off. Every time it triggers it adds ten items to itemCount
. Now I have some parts in here just for demonstration the Future that that waits 3 seconds you probably wouldn't use but since I just used a list of numbers if I didn't do that there would be no loading time. For you grabbing from firebase there probably will be.
final ScrollController _controller = ScrollController();
int scrollPosition = 1;
int itemCount = 20;
bool isLoading = false;
List<int> numbers = [//bunch of numbers];
void _onEndScroll(ScrollMetrics metrics) {
if (metrics.pixels == metrics.maxScrollExtent) {
setState(() {
isLoading = true;
});
Future.delayed(Duration(seconds: 3), () {
setState(() {
if (itemCount + 10 < numbers.length) {
scrollPosition = itemCount;
itemCount = itemCount + 10;
isLoading = false;
} else {
scrollPosition = numbers.length;
itemCount = numbers.length;
isLoading = false;
}
});
// _scollToPosition(); this is the cod that doesn't work
});
}
}
// Function that doesn't work
void _scollToPosition() {
_controller.jumpTo(scrollPosition.toDouble());
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: isLoading
? CircularProgressIndicator()
: NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scrollNotification) {
if (scrollNotification is ScrollEndNotification) {
if (scrollNotification.metrics.pixels ==
scrollNotification.metrics.maxScrollExtent) {
if (itemCount == numbers.length) {
return true;
}
_onEndScroll(scrollNotification.metrics);
}
return false;
}
return false;
},
child: ListView.builder(
shrinkWrap: true,
controller: _controller,
itemCount: itemCount,
itemBuilder: (BuildContext context, int index) =>
TextAndIconWidget(
label: numbers[index].toString(),
),
),
),
),
);
}
This link explains the problem with scrolling to a specific position with ListView
and unfortunately SingleChildScrollView
which has the scroll capability you want doesn't have the itemCount
property you need
So what you want to do is use the part of the code above that detects when you are at the bottom of the list and then query firebase for the next set of brew there are a number of ways to query firebase. You can find the documentation here. You want to find the best way to sort your brews from looking at the github I think your best bet is alphabetic. So what you would do is for querys is
Firestore.instance.collection('brews').where('name', isLessThanOrEqualTo: NameOfLastBrewYouWantLoaded).getDocuments();
Firestore.instance.collection('brews').where('name', isGreaterThanOrEqualTo: NameOfStartingBrew).where('name', isLessThanOrEqualTo: NameOfEnding).getDocuments(); //if your getting duplicates change isGreaterThanOrEqualTo to isGreaterThan and same for isLessThanOrEqualTo
Firestore.instance.collection('brews').where('name', isGreaterThanOrEqualTo: NameOfLastBrewYouLoaded).getDocuments();
These 3 queries would be your initial query than your query for you would you for every query other except the last one.
I hope this wasnt too confusing
Upvotes: 0