alex
alex

Reputation: 130

I am just getting started with flutter and would be nice if anybody can help me out with pagination in this page of the app

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

Answers (2)

wcyankees424
wcyankees424

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

wcyankees424
wcyankees424

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

Related Questions