Pagination In Flutter Using Firebase Cloud Firestore

In this article, we are going to learn about pagination in Flutter using Firebase Cloud Firestore database.

Introduction

 
In this article, we are going to learn about pagination in Flutter using Firebase Cloud Firestore database. As we know that accessing data in small pieces rather than the whole bunch is a better approach in terms of application performance and bandwidth cost, I would like to include that Firebase Firestore bills you according to the number of reads, writes, and delete operations so, this article will be very crucial to those developers who want to use Firebase Cloud Firestore database as backend for their app.
 
We are going to implement the scroll to load feature for loading more data in the below example. Initially, we will load 15 records and then after, whenever the user reaches the end of the list or bottom of the list, we will load another 15 records and so on. So, let’s begin our step by step example tutorial for pagination in Flutter using Firebase Cloud Firestore database.
 

Prerequisites

  • Created New Project named as “flutter_firebase_pagination”. 
  • I am assuming that you are familiar with how to create a Firebase project and initialize the Firestore database in it. If you are a beginner and don’t have an idea about Firestore, you can check my article Firebase Firestore CRUD Operation In Flutter.
  • After creating the Firebase database, create a collection named “products” and add 25 documents manually in products collection. I have attached a screenshot that will make you easily understand how to structure our collection. There are two fields in the document - “name” and “short_desc”.
Pagination In Flutter Using Firebase Cloud Firestore
 

Programming Steps

 
Step 1
 
Open the pubspec.yaml file in your project and add the following dependencies into it.
  1. dependencies:  
  2.  flutter:  
  3.    sdk: flutter  
  4.  cupertino_icons: ^0.1.2  
  5.  cloud_firestore: ^0.12.7  
Step 2
 
Open the main.dart file and import Firestore package.
  1. import 'package:cloud_firestore/cloud_firestore.dart';  
Step 3
 
Initialize the Firestore instance in the state class.
  1. Firestore firestore = Firestore.instance;  
Step 4
 
Define another variable for storing data and tracking the load progress.
  1. List<DocumentSnapshot> products = []; // stores fetched products  
  2.   
  3. bool isLoading = false// track if products fetching  
  4.   
  5. bool hasMore = true// flag for more products available or not  
  6.   
  7. int documentLimit = 10; // documents to be fetched per request  
  8.   
  9. DocumentSnapshot lastDocument; // flag for last document from where next 10 records to be fetched  
  10.   
  11. ScrollController _scrollController = ScrollController(); // listener for listview scrolling  
Step 5
 
Define the getProducts() function to get initial 10 documents.
  1. getProducts() async {  
  2.    if (!hasMore) {  
  3.      print('No More Products');  
  4.      return;  
  5.    }  
  6.    if (isLoading) {  
  7.      return;  
  8.    }  
  9.    setState(() {  
  10.      isLoading = true;  
  11.    });  
  12.    QuerySnapshot querySnapshot;  
  13.    if (lastDocument == null) {  
  14.      querySnapshot = await firestore  
  15.          .collection('products')  
  16.          .orderBy('name')  
  17.          .limit(documentLimit)  
  18.          .getDocuments();  
  19.    } else {  
  20.      querySnapshot = await firestore  
  21.          .collection('products')  
  22.          .orderBy('name')  
  23.          .startAfterDocument(lastDocument)  
  24.          .limit(documentLimit)  
  25.          .getDocuments();  
  26.      print(1);  
  27.    }  
  28.    if (querySnapshot.documents.length < documentLimit) {  
  29.      hasMore = false;  
  30.    }  
  31.    lastDocument = querySnapshot.documents[querySnapshot.documents.length - 1];  
  32.    products.addAll(querySnapshot.documents);  
  33.    setState(() {  
  34.      isLoading = false;  
  35.    });  
  36.  }  
Step 6
 
Define the Scrolling Listener. If the user scroll reacts to 20% of the device height, we will fetch more documents. We have defined the login in the listener.
  1. _scrollController.addListener(() {  
  2.      double maxScroll = _scrollController.position.maxScrollExtent;  
  3.      double currentScroll = _scrollController.position.pixels;  
  4.      double delta = MediaQuery.of(context).size.height * 0.20;  
  5.      if (maxScroll - currentScroll <= delta) {  
  6.        getProducts();  
  7.      }  
  8.    });  
Step 7
 
Generated UI in build method.
  1. @override  
  2.  Widget build(BuildContext context) {  
  3.    return Scaffold(  
  4.      appBar: AppBar(  
  5.        title: Text('Flutter Pagination with Firestore'),  
  6.      ),  
  7.      body: Column(children: [  
  8.        Expanded(  
  9.          child: products.length == 0  
  10.              ? Center(  
  11.                  child: Text('No Data...'),  
  12.                )  
  13.              : ListView.builder(  
  14.                  controller: _scrollController,  
  15.                  itemCount: products.length,  
  16.                  itemBuilder: (context, index) {  
  17.                    return ListTile(  
  18.                      contentPadding: EdgeInsets.all(5),  
  19.                      title: Text(products[index].data['name']),  
  20.                      subtitle: Text(products[index].data['short_desc']),  
  21.                    );  
  22.                  },  
  23.                ),  
  24.        ),  
  25.        isLoading  
  26.            ? Container(  
  27.                width: MediaQuery.of(context).size.width,  
  28.                padding: EdgeInsets.all(5),  
  29.                color: Colors.yellowAccent,  
  30.                child: Text(  
  31.                  'Loading',  
  32.                  textAlign: TextAlign.center,  
  33.                  style: TextStyle(  
  34.                    fontWeight: FontWeight.bold,  
  35.                  ),  
  36.                ),  
  37.              )  
  38.            : Container()  
  39.      ]),  
  40.    );  
  41.  }  

Step 8

 
Great! You are done with Flutter pagination using Firebase Cloud Firestore database. For the full example code, you can download the zip or pull my repository.
 
NOTE
PLEASE CHECK OUT GIT REPO FOR FULL SOURCE CODE. YOU NEED TO ADD YOUR google-services.json FILE IN ANDROID => APP FOLDER.
 
Possible ERRORS
 
Error: import androidx.annotation.NonNull;
 
SOLUTION
 
Add the below lines in android/gradle.properties file,
 
android.useAndroidX=true
android.enableJetifier=true
 

Conclusion

 
In this article, we have learned how to implement pagination in Flutter using Firebase Cloud Firestore database and how we can improve our app performance and reduce bandwidth usage.