Flutter - Infinite Scroll Pagination
Last Updated :
24 Apr, 2025
Infinite lists are a way to display paginated data efficiently. When a user scrolls to the end of the current page, more data is fetched and added to the list. This is also known as endless scrolling pagination, infinite scrolling pagination, auto-pagination, lazy loading pagination, and progressive loading pagination. It is good because it loads data only when the user interacts with the list. When data in the list is bigger it is better to use this widget for the app's performance optimizations and Interactive UI for Users.
What Will We Make?
We will create a user list with his/her name and email address. We get these data from Punk API. We will call an API Call to get data from it. A sample video is given below to get an idea about what we are going to do in this article.
Step By Step Implementation
Step 1: Create a New Project in Android Studio
To set up Flutter Development on Android Studio please refer to Android Studio Setup for Flutter Development, and then create a new project in Android Studio please refer to Creating a Simple Application in Flutter.
Step 2: Add Package in your pubspec.yaml file
Dart
dependencies:
infinite_scroll_pagination: ^4.0.0
Step 3: Import the library in your page
Dart
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
Step 4: Add Controllers and page size
Pagination Controllers is controller to manage the data refresh it,add page listeners
Dart
final int _pageSize = 20;
final PagingController<int, dynamic> _pagingController =
PagingController(firstPageKey: 1);
Step 5: Add API Request and get data
To get the data from sample API we will use http package
Dart
class RemoteApi {
static Future<List<dynamic>?> getBeerList(
// Page means on which page you are currently
int page,
// Limit per page you want to set
int limit,
) async {
try {
// Request the API on url
final response = await http.get(
Uri.parse(
'https://api.punkapi.com/v2/beers?'
'page=$page'
'&per_page=$limit',
),
);
if (response.statusCode == 200) {
// Decode the response
final mybody = jsonDecode(response.body);
return mybody;
}
} catch (e) {
print("Error $e");
}
return null;
}
}
Step 6: Update the API data in controllers and add listener to it
We create a function which will add the data in page controller
Dart
Future<void> _fetchPage(int pageKey) async {
try {
// get api /beers list from pages
final newItems = await RemoteApi.getBeerList(pageKey, _pageSize);
// Check if it is last page
final isLastPage = newItems!.length < _pageSize;
// If it is last page then append
// last page else append new page
if (isLastPage) {
_pagingController.appendLastPage(newItems);
} else {
// Appending new page when it is not last page
final nextPageKey = pageKey + 1;
_pagingController.appendPage(newItems, nextPageKey);
}
}
// Handle error in catch
catch (error) {
print(_pagingController.error);
// Sets the error in controller
_pagingController.error = error;
}
}
We will add a listener in init state to call the previous function whenver user go to next page or when more data is required to load
Dart
@override
void initState() {
_pagingController.addPageRequestListener((pageKey) {
_fetchPage(pageKey);
});
super.initState();
}
Step 7: We will add UI in body to show infinite scroll page view
Now we will add a paged listview in our screens
Dart
Scaffold(
// Page Listview with divider as a separation
body: PagedListView<int, dynamic>.separated(
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<dynamic>(
animateTransitions: true,
itemBuilder: (_, item, index) => ListTile(
leading: CircleAvatar(
radius: 20,
backgroundImage: NetworkImage(item["image_url"]),
),
title: Text(item["name"]),
),
),
separatorBuilder: (_, index) => const Divider(),
),
)
Step 8: Dispose the Controller
Dart
@override
void dispose() {
_pagingController.dispose();
super.dispose();
}
Step 9: Refresh the listview on pulling down
Dart
// Refrsh Indicator pull down
RefreshIndicator(
onRefresh: () => Future.sync(
// Refresh through page controllers
() => _pagingController.refresh(),
),child:...)
You are good to go!!!
Additional Tips
We have used the listview seperated here to show the data. You can use different widget available in
- GridView: A widget for creating a scrollable grid layout of items.
- SliverGrid: Similar to GridView, but used within a CustomScrollView for more advanced scrolling effects.
- ListView: Displays a scrollable list of widgets in a single column.
- SliverList: A list within a CustomScrollView for dynamic and optimized scrolling.
- Custom Layout: Custome layout as per you requirement
In all this option seperated constructor is also available
Complete Source Code
Dart
class InfiniteScrollExample extends StatefulWidget {
const InfiniteScrollExample({super.key});
@override
State<InfiniteScrollExample> createState() => _InfiniteScrollExampleState();
}
class _InfiniteScrollExampleState extends State<InfiniteScrollExample> {
final int _pageSize = 20;
final PagingController<int, dynamic> _pagingController =
PagingController(firstPageKey: 1);
@override
void initState() {
_pagingController.addPageRequestListener((pageKey) {
_fetchPage(pageKey);
});
super.initState();
}
Future<void> _fetchPage(int pageKey) async {
try {
// get api /beers list from pages
final newItems = await RemoteApi.getBeerList(pageKey, _pageSize);
// Check if it is last page
final isLastPage = newItems!.length < _pageSize;
// If it is last page then append last page else append new page
if (isLastPage) {
_pagingController.appendLastPage(newItems);
} else {
// Appending new page when it is not last page
final nextPageKey = pageKey + 1;
_pagingController.appendPage(newItems, nextPageKey);
}
}
// Handle error in catch
catch (error) {
print(_pagingController.error);
// Sets the error in controller
_pagingController.error = error;
}
}
@override
Widget build(BuildContext context) =>
// Refrsh Indicator pull down
RefreshIndicator(
onRefresh: () => Future.sync(
// Refresh through page controllers
() => _pagingController.refresh(),
),
child: Scaffold(
appBar: AppBar(
title: const Text("Pagination Scroll Flutter Template"),
),
// Page Listview with divider as a separation
body: PagedListView<int, dynamic>.separated(
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<dynamic>(
animateTransitions: true,
itemBuilder: (_, item, index) => ListTile(
leading: CircleAvatar(
radius: 20,
backgroundImage: NetworkImage(item["image_url"]),
),
title: Text(item["name"]),
),
),
separatorBuilder: (_, index) => const Divider(),
),
),
);
@override
void dispose() {
_pagingController.dispose();
super.dispose();
}
}
class RemoteApi {
static Future<List<dynamic>?> getBeerList(
// Page means on which page you are currently
int page,
// Limit per page you want to set
int limit,
) async {
try {
// Request the API on url
final response = await http.get(
Uri.parse(
'https://api.punkapi.com/v2/beers?'
'page=$page'
'&per_page=$limit',
),
);
if (response.statusCode == 200) {
// Decode the response
final mybody = jsonDecode(response.body);
return mybody;
}
} catch (e) {
print("Error $e");
}
return null;
}
}
Output:
Similar Reads
Flutter - UI Orientation
All applications should be able to adjust their User Interface (UI) based on the orientation of the phone. By orientation, we implicate the portrait and landscape mode in smartphones rather the physical orientation. In, Flutter it is done so by using the OrientationBuilder, which determines the app'
2 min read
Flutter - Nested Scroll View
In Flutter, you can use a NestedScrollView widget to create a scrollable view with multiple scrolling sections that can scroll independently of each other. This is commonly used when you have a header that should remain visible while the content below it scrolls. In this article, we are going to imp
4 min read
Flutter - Smooth Page Indicator
Smooth Page Indicator is a customizable animated page indicator with the following set of built-in effects. WormExpanding DotsScrolling DotsJumping DotsSlideScaleSwapGetting Start First, we need to add dependency into the pubspec.yaml file. dependencies: smooth_page_indicator: ^1.0.0+2 Don't forget
3 min read
Flutter - Scroll Snap List
The scroll_snap_list package provides a wrapper that wraps around the ListView.builder widget to enable snapping event on List items. It can be modified to horizontal or vertical snapping based on the requirements. It is also important to note that it doesn't make use of less or no animation. In thi
4 min read
Routes and Navigator in Flutter
Route: Apps are the new trend. The number of apps available in the Play Store and App Store nowadays is quite a lot. The apps display their content in a full-screen container called pages or screens. In flutter, the pages or screens are called Routes. In android, these pages/screens are referred to
4 min read
Flutter - Rotate Transition
In Flutter, the page_transition package is used to create beautiful page transitions. It provides a wide range of effects that can be used from moving from one route to another. It is very convenient to use. In this article, we will explore the same by building a simple application.Steps to Implemen
3 min read
Flutter - Preserve Scroll Position of ListView Using Page Storage
In this article, we will learn How to Preserve the Scroll Position of Listview Using Page Storage. So let's get started. Step By Step Implementation Step 1: Building main.dart page We have built an AppbarThe elevated button is used with help of which we will navigate to the next page MyList where 10
4 min read
Flutter - Navigating Through Gesture on Images
Flutter apps may have multiple screens or pages. Pages are groups of functionalities. The user navigates between different pages to use different functionalities. Concepts like pages are called routes in Flutter. We can Use Navigator.push() to navigate to a new route and Navigator.pop() to navigate
5 min read
NotificationListener Widget in Flutter
In Flutter, every Scrollable sends Notifications that contain information about the current scroll state. So to catch these notifications we use NotificationListener Widget. NotificationListener Widget will listen for Notifications bubbling up the tree. In this, article we will learn about Notificat
4 min read
Flutter - Navigate From One Screen to Another
Flutter apps may have multiple screens or pages. Pages are groups of functionalities. The user navigates between different pages to use different functionalities. Concepts like pages are called routes in Flutter. We can use Navigator.push() to navigate to a new route and Navigator.pop() to navigate
3 min read