Infinite Scrolling Pagination in Flutter
Learn how to implement infinite scrolling pagination (also known as lazy loading) in Flutter using the Infinite Scroll Pagination package. By Edson Bueno.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Infinite Scrolling Pagination in Flutter
20 mins
- Getting Started
- Diving Into the Code
- Understanding Pagination
- Automating Pagination
- Creating a Paginated ArticleListView
- Swapping List Widgets
- Engineering Infinite Scrolling Pagination
- Getting to Know the Package
- Instantiating a PagingController
- Fetching Pages
- Using a Paginated ListView
- Building List Items
- Creating a Builder Delegate
- Applying Filters
- Where to Go From Here?
Creating a Builder Delegate
For the final touch, fill that same gap in code by specifying this new parameter to your PagedListView
, in the same level as pagingController
, padding
and separatorBuilder
:
builderDelegate: PagedChildBuilderDelegate<Article>(
itemBuilder: (context, article, index) => ArticleListItem(
article: article,
),
firstPageErrorIndicatorBuilder: (context) => ErrorIndicator(
error: _pagingController.error,
onTryAgain: () => _pagingController.refresh(),
),
noItemsFoundIndicatorBuilder: (context) => EmptyListIndicator(),
),
PagedChildBuilderDelegate
is a collection of builders for every widget involved in infinite scrolling pagination.
Although you’ve only specified three parameters in your code, knowing all seven of them might save you in the future:
-
itemBuilder
: This builds your list items. It’s the only required parameter; all others have defaults. -
firstPageErrorIndicatorBuilder
: This builds a widget that informs the user the occurrence of an error fetching the first page. In this scenario, you won’t yet have any list items loaded, so you’ll want this widget to fill the entire space. Make sure you callrefresh()
on your controller if you decide to add a retry button to your indicator — take another look at the previous code snippet and you’ll see it. -
newPageErrorIndicatorBuilder
: This also indicates an error, but for subsequent page requests. As you already have some items loaded, the widget you build here appears at the bottom of your list. If you add a retry button to your indicator, make sure you callretryLastRequest()
on your controller when the user taps your button. -
firstPageProgressIndicatorBuilder
: This builds the widget that’ll show while loading the first page. You won’t yet have any items loaded, so you’ll want this widget to fill the entire space. -
newPageProgressIndicatorBuilder
: This is similar to the previous builder, but it shows while loading subsequent pages. As you already have some items loaded, the widget you build here appears at the bottom of your list. -
noItemsFoundIndicatorBuilder
: What if your API successfully returns an empty list? Technically that’s not an error, and it’s usually associated with too many filter options selected. The widget you build here covers this “zero items” scenario. -
noMoreItemsIndicatorBuilder
: Here it is, the gold at the end of the rainbow! This is where you optionally build a widget to display when the user finally reaches the end of your list. Mystery solved!
Build and run. Try turning off your device’s connection and using swipe to refresh as shown in the GIF below. This will help you test both RefreshIndicator
and the custom error indicator widget.
Hmm, there’s a bug in your app. Apparently that wasn’t the final touch after all. Try figuring out what’s wrong. If you’re stuck, click the Reveal button below to find out what it is.
[spoiler title=”Filters Bug”]
Applying filters doesn’t seem to be taking any effect.
[/spoiler]
Applying Filters
You know what they say: Be suspicious if your code works on the first try. Well, yours didn’t, so you’re probably doing something right!
Here’s what’s causing the bug: When the user applies filters, ArticleListScreen
rebuilds your PagedArticleListView
with a brand-new ListPreferences
, but no one warned your PagingController
about the change.
The place for solving this is lib/ui/list/paged_article_list_view.dart. Inside _PagedArticleListViewState
, add the following function override:
@override
void didUpdateWidget(PagedArticleListView oldWidget) {
if (oldWidget.listPreferences != widget.listPreferences) {
_pagingController.refresh();
}
super.didUpdateWidget(oldWidget);
}
This is what the code above is saying: Whenever the widget associated with this State
subclass updates, if the listPreferences
also changed, refresh the _pagingController
by calling refresh()
on it.
Mission accomplished. Time to build and run readwenderlich for the last time and allow the wonder of infinite scrolling pagination to amaze you. You did it!
Where to Go From Here?
Download the completed project files by clicking the Download Materials button at the top or bottom of the tutorial.
Now for the coolest part: The Infinite Scroll Pagination package comes with replacement parts for your middle piece. Choose whichever suits your next layout the best.
You can find more details on these extra pieces in the package’s cookbook.
Here’s a suggestion: The endpoint you used to fetch your articles accepts search queries. How about using that to add search support to readwenderlich?
We hope you enjoyed this tutorial. If you have any questions or comments, please join the forum discussion below!