Pagination and Infinite Lists
Pagination is a technique that lets you load large sets of data in smaller, manageable chunks.
In Flutter, infinite scrolling is a common way to implement pagination, where more data is fetched as the user reaches the end of a scrollable list. This approach keeps your app responsive and efficient, especially when working with remote APIs that return long lists of items.
main.dart
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485import 'package:flutter/material.dart'; void main() => runApp(PaginatedListApp()); class PaginatedListApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: PaginatedListScreen(), ); } } class PaginatedListScreen extends StatefulWidget { @override _PaginatedListScreenState createState() => _PaginatedListScreenState(); } class _PaginatedListScreenState extends State<PaginatedListScreen> { final ScrollController _controller = ScrollController(); final List<int> _items = []; bool _isLoading = false; bool _hasMore = true; int _page = 0; final int _limit = 20; @override void initState() { super.initState(); _fetchItems(); _controller.addListener(() { if (_controller.position.pixels >= _controller.position.maxScrollExtent - 200 && !_isLoading && _hasMore) { _fetchItems(); } }); } Future<void> _fetchItems() async { setState(() { _isLoading = true; }); // Simulate API call delay await Future.delayed(Duration(seconds: 2)); // Simulate API response List<int> fetched = List.generate(_limit, (i) => _page * _limit + i); setState(() { _items.addAll(fetched); _isLoading = false; _page++; if (fetched.length < _limit) { _hasMore = false; } }); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Paginated List')), body: ListView.builder( controller: _controller, itemCount: _items.length + (_hasMore ? 1 : 0), itemBuilder: (context, index) { if (index < _items.length) { return ListTile(title: Text('Item [${_items[index]}')); } else { return Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: Center(child: CircularProgressIndicator()), ); } }, ), ); } }
Scroll controllers allow you to listen for scroll events and determine when the user is near the end of a list. In the paginated list example, a ScrollController is used to trigger the loading of more items as the user scrolls close to the bottom. A loading indicator, such as CircularProgressIndicator, is displayed at the end of the list while new data is being fetched. This provides clear feedback and ensures a smooth user experience during incremental data loading.
main.dart
123456789void main() { List<String> currentItems = ['Apple', 'Banana', 'Cherry']; List<String> newItems = ['Date', 'Elderberry']; // Append newItems to currentItems currentItems.addAll(newItems); print(currentItems); // Output: [Apple, Banana, Cherry, Date, Elderberry] }
Thanks for your feedback!
Ask AI
Ask AI
Ask anything or try one of the suggested questions to begin our chat
Can you show me a sample code for implementing infinite scrolling in Flutter?
What are some best practices for managing state in paginated lists?
How do I handle errors when loading more data in a paginated list?
Awesome!
Completion rate improved to 9.09
Pagination and Infinite Lists
Swipe to show menu
Pagination is a technique that lets you load large sets of data in smaller, manageable chunks.
In Flutter, infinite scrolling is a common way to implement pagination, where more data is fetched as the user reaches the end of a scrollable list. This approach keeps your app responsive and efficient, especially when working with remote APIs that return long lists of items.
main.dart
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485import 'package:flutter/material.dart'; void main() => runApp(PaginatedListApp()); class PaginatedListApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: PaginatedListScreen(), ); } } class PaginatedListScreen extends StatefulWidget { @override _PaginatedListScreenState createState() => _PaginatedListScreenState(); } class _PaginatedListScreenState extends State<PaginatedListScreen> { final ScrollController _controller = ScrollController(); final List<int> _items = []; bool _isLoading = false; bool _hasMore = true; int _page = 0; final int _limit = 20; @override void initState() { super.initState(); _fetchItems(); _controller.addListener(() { if (_controller.position.pixels >= _controller.position.maxScrollExtent - 200 && !_isLoading && _hasMore) { _fetchItems(); } }); } Future<void> _fetchItems() async { setState(() { _isLoading = true; }); // Simulate API call delay await Future.delayed(Duration(seconds: 2)); // Simulate API response List<int> fetched = List.generate(_limit, (i) => _page * _limit + i); setState(() { _items.addAll(fetched); _isLoading = false; _page++; if (fetched.length < _limit) { _hasMore = false; } }); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Paginated List')), body: ListView.builder( controller: _controller, itemCount: _items.length + (_hasMore ? 1 : 0), itemBuilder: (context, index) { if (index < _items.length) { return ListTile(title: Text('Item [${_items[index]}')); } else { return Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: Center(child: CircularProgressIndicator()), ); } }, ), ); } }
Scroll controllers allow you to listen for scroll events and determine when the user is near the end of a list. In the paginated list example, a ScrollController is used to trigger the loading of more items as the user scrolls close to the bottom. A loading indicator, such as CircularProgressIndicator, is displayed at the end of the list while new data is being fetched. This provides clear feedback and ensures a smooth user experience during incremental data loading.
main.dart
123456789void main() { List<String> currentItems = ['Apple', 'Banana', 'Cherry']; List<String> newItems = ['Date', 'Elderberry']; // Append newItems to currentItems currentItems.addAll(newItems); print(currentItems); // Output: [Apple, Banana, Cherry, Date, Elderberry] }
Thanks for your feedback!