Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Learn Pagination and Infinite Lists | Real Data in UI
Practice
Projects
Quizzes & Challenges
Quizzes
Challenges
/
Flutter REST API Integration

bookPagination and Infinite Lists

When you need to display large lists of data from an API, loading everything at once is rarely practical. APIs often provide paginationβ€”a way to fetch data in chunks or "pages"β€”so your app only loads and displays a limited number of items at a time. This approach is essential for performance, usability, and network efficiency, especially when dealing with thousands of records.

main.dart

main.dart

copy
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
import 'package:flutter/material.dart'; import 'dart:async'; import 'dart:math'; void main() { runApp(PaginatedListApp()); } class PaginatedListApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Pagination Demo', home: PaginatedListScreen(), ); } } class PaginatedListScreen extends StatefulWidget { @override _PaginatedListScreenState createState() => _PaginatedListScreenState(); } class _PaginatedListScreenState extends State<PaginatedListScreen> { final ScrollController _scrollController = ScrollController(); final List<String> _items = []; bool _isLoading = false; int _currentPage = 1; final int _pageSize = 20; bool _hasMore = true; @override void initState() { super.initState(); _fetchPage(); _scrollController.addListener(_onScroll); } @override void dispose() { _scrollController.dispose(); super.dispose(); } Future<List<String>> _fetchData(int page, int pageSize) async { // Simulate API delay await Future.delayed(Duration(seconds: 2)); // Simulate total 100 items in API int totalItems = 100; int start = (page - 1) * pageSize; if (start >= totalItems) return []; int end = min(start + pageSize, totalItems); return List.generate(end - start, (i) => 'Item οΏ½24{start + i + 1}'); } void _fetchPage() async { if (_isLoading || !_hasMore) return; setState(() { _isLoading = true; }); List<String> newItems = await _fetchData(_currentPage, _pageSize); setState(() { _items.addAll(newItems); _isLoading = false; _hasMore = newItems.length == _pageSize; if (_hasMore) _currentPage++; }); } void _onScroll() { if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent - 200 && !_isLoading && _hasMore) { _fetchPage(); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Paginated List')), body: ListView.builder( controller: _scrollController, itemCount: _items.length + (_isLoading || _hasMore ? 1 : 0), itemBuilder: (context, index) { if (index < _items.length) { return ListTile(title: Text(_items[index])); } else if (_hasMore || _isLoading) { return Padding( padding: const EdgeInsets.all(16.0), child: Center(child: CircularProgressIndicator()), ); } return SizedBox.shrink(); }, ), ); } }
Note
Note

To avoid duplicate API calls during infinite scrolling, always check if a request is already in progress before starting a new one. Use a flag like '_isLoading' to prevent multiple simultaneous requests, which can lead to repeated data or wasted bandwidth.

The code above demonstrates a paginated ListView that fetches more items from a simulated API as you scroll. A ScrollController listens for the user's scroll position. When the user nears the end of the list, the controller triggers another API call to fetch the next page. The _currentPage variable keeps track of which page to request next, and _hasMore ensures that fetching stops when all data has been loaded. This pattern efficiently loads new items only as needed, providing a smooth infinite scrolling experience.

question mark

Why is pagination important when displaying large lists from an API?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

SectionΒ 2. ChapterΒ 2

Ask AI

expand

Ask AI

ChatGPT

Ask anything or try one of the suggested questions to begin our chat

bookPagination and Infinite Lists

Swipe to show menu

When you need to display large lists of data from an API, loading everything at once is rarely practical. APIs often provide paginationβ€”a way to fetch data in chunks or "pages"β€”so your app only loads and displays a limited number of items at a time. This approach is essential for performance, usability, and network efficiency, especially when dealing with thousands of records.

main.dart

main.dart

copy
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
import 'package:flutter/material.dart'; import 'dart:async'; import 'dart:math'; void main() { runApp(PaginatedListApp()); } class PaginatedListApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Pagination Demo', home: PaginatedListScreen(), ); } } class PaginatedListScreen extends StatefulWidget { @override _PaginatedListScreenState createState() => _PaginatedListScreenState(); } class _PaginatedListScreenState extends State<PaginatedListScreen> { final ScrollController _scrollController = ScrollController(); final List<String> _items = []; bool _isLoading = false; int _currentPage = 1; final int _pageSize = 20; bool _hasMore = true; @override void initState() { super.initState(); _fetchPage(); _scrollController.addListener(_onScroll); } @override void dispose() { _scrollController.dispose(); super.dispose(); } Future<List<String>> _fetchData(int page, int pageSize) async { // Simulate API delay await Future.delayed(Duration(seconds: 2)); // Simulate total 100 items in API int totalItems = 100; int start = (page - 1) * pageSize; if (start >= totalItems) return []; int end = min(start + pageSize, totalItems); return List.generate(end - start, (i) => 'Item οΏ½24{start + i + 1}'); } void _fetchPage() async { if (_isLoading || !_hasMore) return; setState(() { _isLoading = true; }); List<String> newItems = await _fetchData(_currentPage, _pageSize); setState(() { _items.addAll(newItems); _isLoading = false; _hasMore = newItems.length == _pageSize; if (_hasMore) _currentPage++; }); } void _onScroll() { if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent - 200 && !_isLoading && _hasMore) { _fetchPage(); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Paginated List')), body: ListView.builder( controller: _scrollController, itemCount: _items.length + (_isLoading || _hasMore ? 1 : 0), itemBuilder: (context, index) { if (index < _items.length) { return ListTile(title: Text(_items[index])); } else if (_hasMore || _isLoading) { return Padding( padding: const EdgeInsets.all(16.0), child: Center(child: CircularProgressIndicator()), ); } return SizedBox.shrink(); }, ), ); } }
Note
Note

To avoid duplicate API calls during infinite scrolling, always check if a request is already in progress before starting a new one. Use a flag like '_isLoading' to prevent multiple simultaneous requests, which can lead to repeated data or wasted bandwidth.

The code above demonstrates a paginated ListView that fetches more items from a simulated API as you scroll. A ScrollController listens for the user's scroll position. When the user nears the end of the list, the controller triggers another API call to fetch the next page. The _currentPage variable keeps track of which page to request next, and _hasMore ensures that fetching stops when all data has been loaded. This pattern efficiently loads new items only as needed, providing a smooth infinite scrolling experience.

question mark

Why is pagination important when displaying large lists from an API?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

SectionΒ 2. ChapterΒ 2
some-alt