Flutter Pagination Guide

How to Paginate Your Data in Flutter?

Posted by Aakash Mehta

10 Aug 20 3 min read

A simple workaround for the infinite scroll (Pagination) in Flutter ListView!

We face many requirements in our daily flutter app development for infinite scrolling (pagination)in ListView.

We start creating ListView then create a list of widgets and set scroll listener and set error or failure scenarios and then lastly, stop the pagination when data loading is completed.

What if I tell you that you have one widget in which you just need to pass your callback with data which will be called when user reach to the end of the list.

image

So I’ll first mention how we can implement pagination with a straight forward way and then we’ll look for some better approach.

[@portabletext/react] Unknown block type "separator", specify a component for it in the `components.types` prop

1. Implement Flutter Pagination from Scratch

So one initial note to mobile developers that in Android or iOS we were reusing one single view in the list with different data, for eg. if in one viewport there are 7 items visible then, view objects will be created for the same to be reused.

But in Flutter, architecture is designed in a manner that whenever data is updated all view components(or you can say widget) will be recreated.

  • So first we need one ListView widget and one scroll listener to listen to the event when the user reaches at the end of the list to update the data.
 Widget _createListView(List<NewsResponseItem> itemList) {
    ScrollController _scrollController = ScrollController();
    _scrollController.addListener(() {
      if (_scrollController.position.maxScrollExtent ==
          _scrollController.position.pixels) {
        if (!isLoading) {
          isLoading = !isLoading;
          // Perform event when user reach at the end of list (e.g. do Api call)
        }
      }
    });
    return ListView.builder(
        controller: _scrollController,
        itemCount: itemList.length,
        itemBuilder: (BuildContext context, int index) =>
            NewsListItem(itemList[index]));
  }
  • Secondly, you need to return an appropriate widget on data retrieves. It can be a progress bar, list of widgets or error text as shown in the below code snippet. You can use the Bloc — Stream builder pattern to manage progress, data or error state.
Widget _getPage(EventModel model) {
    isLoading = false;
    if (model.progress) {
      // Return progress widget if item list is empty else return same list widget to rebuild
      if (itemList.isEmpty) {
        return ProgressIndicatorWidget();
      } else {
        return _createListView(itemList);
      }
    } else if (model.response != null) {
      // Add/remove null value to show/hide progress bar and update list widget with newer items.
      if (itemList.contains(null)) {
        itemList.remove(null);
      }
      itemList.addAll(model.response);
      itemList.add(null);
      return _createListView(itemList);
    } else {
      // Show error message when unable to fetch items.
      if (itemList.isEmpty) {
        return ErrorTextWidget(model.error);
      } else {
        return _createListView(itemList);
      }
    }
  }
  • You can display progress at the bottom by returning widget conditionally. You can return view if data retrieves or progress if data is null as shown in below snippet.
Widget _rowWidget(BuildContext context, NewsResponseItem newsResponseItem) {
    if (newsResponseItem == null) {
      return Center(
        child: ProgressIndicatorWidget(),
      );
    } else {
      return Material(
        child: InkWell(
          onTap: () {
            _navigateToWebViewScreen(context, newsResponseItem);
          },
          child: Padding(
            padding: EdgeInsets.only(top: 16, bottom: 16, left: 10, right: 10),
            child: Container(
              decoration: BoxDecoration(
                  color: Colors.grey[50],
                  boxShadow: [BoxShadow(color: Colors.grey, blurRadius: 10)],
                  border: Border.all(color: Colors.grey[400], width: 1.0),
                  borderRadius: BorderRadius.circular(5)),
              child: Padding(
                padding: EdgeInsets.all(10),
                child: Text(
                  newsResponseItem.title,
                  style: TextStyle(fontSize: 18),
                ),
              ),
            ),
          ),
        ),
      );
    }
  }

You can get the full source for above implementation from here

Now let’s head up to some smart workaround.

[@portabletext/react] Unknown block type "separator", specify a component for it in the `components.types` prop

2. Implement pagination using Flutter Pagination Helper

So I figured out some common and boilerplate code and made a generalized solution and created a library for that named Flutter Pagination Helper.

Here are the steps to implement pagination in flutter

  • Implement flutter pagination dependency by declaring that in pubspec.yaml
dependencies:
flutter_pagination_helper: ^1.0.0+5
  • Import required files and initialize PaginatedListWidget as follows.
class CustomProgressWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: PaginatedListWidget(
progressWidget: Center(
child: Text("Loading..."),
),
itemListCallback: OnScrollCallback()),
),
);
}
}

where progressWidget is an optional parameter to assign your custom progress widget and itemListCallback is required parameter in which you need to provide the call back for data in the form of Future.

  • Implement ItemListCallback as bellow.
class OnScrollCallback<T extends Widget> extends ItemListCallback {
@override
Future<EventModel<T>> getItemList() {
// TODO: implement getItemList
return null;
}
}
  • Here you need to return your items in the form of Future<EventModel<T>>

Where EventModel is model which stores different states such as progress bar visibility, data, and error message as below.

class EventModel<T extends Widget> {
final bool progress;
final List<T> data;
final String error;
final bool stopLoading;

EventModel({this.progress, this.data, this.error, this.stopLoading});
}

And your output for the list with default progress widget will be as bellow.

Flutter Pagination with Default Progress Widget

And the output for a list with custom progress widget will be as bellow.

Flutter Pagination with Custom Progress Widget

Conclusion :

For the major requirement of Flutter pagination ListView, Flutter Pagination Helper will be a more suitable option and for more specification, you can go with the first option.

You can find the full source for the library at

[@portabletext/react] Unknown block type "urllink", specify a component for it in the `components.types` prop

FAQS

Stay curious, Questions?

What is pagination in flutter?

Click to show answer

Pagination in Flutter means the process of dividing digital content into discrete pages.

What is the purpose of pagination?

Click to show answer

Pagination is used to divide multiple digital data of an application and showcase it across multiple pages. So if you have a huge amount of data to be displayed on your web or mobile application, you can use pagination to divide the content across multiple pages, but in the single space. The most prominent examples of pagination is Google Search Results Pages (SERPs), Blogs of various websites, etc.

How do you use pageview in Flutter?

Click to show answer

PageView widget in Flutter allows you to create pages and define how they need to be scrolled and in which direction. You can use PageView in Flutter in three different ways, 1. Using the PageView Constructor directly for Static pageviews 2. Using the PageView.Builder for creating Dynamic pageviews 3. PageView.Custom for creating custom scroll actions or animations

How do you add carousel in Flutter?

Click to show answer

Carousels show multiple items one at a time. If you want to add carousel (slider image) in your Flutter application, follow this process, 1. Use carousel_slider package 2. Add dependency to your pubspec.yaml file 3. Add images to assets 4. Import carousel package into the Dart file 5. Prepare UI for carousel 6. Create the carousel (slider image)

How do I add scrollbar to my Flutter app?

Click to show answer

Since Flutter doesn't provide the inbuilt feature to show Scrollbar, you can instead use a Flutter widget, "scrollbar()". Use the property, isAlwaysShown: true with the Scrollbar widget and create a ScrollController in the State object before passing it manually to the ListView controller. This is how you can add scrollbar to your Flutter app.

What is infinite scroll pagination?

Click to show answer

Infinite Scroll Pagination is a functionality in Flutter that gives the provision for scrolling the data endlessly, which is user-friendly as users don’t have to move to multiple pages, and data gets loaded continuously.

By Infinite scroll pagination, the continuous loading of data is efficiently taken care of.

How do you make an infinite scroll in Flutter?

Click to show answer

There are several ways in which you can make an infinite scroll in Flutter. Some of the prominent ways are-

i) By Making Use of ListView

ii) Using the packages of ‘infinite__scroll__pagination’

iii) By Using ScrollController

How do you Paginate in a flutter firebase?

Click to show answer

The general steps to paginate in flutter firebase are:

Step 1: Fetch the relevant data from the firebase.

Step 2: Once the data is fetched, rank them in order.

Step 3: Set the UI of the app by initializing and making the necessary changes. Set the ScrollController, add the listener, and make the list that is to be paginated.

Step4: Now, you are completed with the pagination in the flutter firebase. Verify and resolve the errors if any.