Flutter中使用ListView.builder实现分页功能
Flutter ListView滚动到底部分页加载(每页10条)实现方案
核心实现思路
- 维护关键状态:当前页码、总数据列表、是否正在加载、是否已加载全部数据
- 通过
ScrollController监听ListView滚动位置,设置提前量触发加载(提升用户体验) - 触发加载前先校验状态,避免重复请求或无效请求
- 加载完成后更新数据与状态,结束加载状态
完整代码实现
import 'package:flutter/material.dart'; class PaginationListView extends StatefulWidget { const PaginationListView({super.key}); @override State<PaginationListView> createState() => _PaginationListViewState(); } class _PaginationListViewState extends State<PaginationListView> { final ScrollController _scrollController = ScrollController(); List<String> _dataList = []; int _currentPage = 1; final int _pageSize = 10; bool _isLoading = false; bool _hasMore = true; @override void initState() { super.initState(); _loadData(); _scrollController.addListener(_onScroll); } @override void dispose() { _scrollController.dispose(); super.dispose(); } void _onScroll() { // 距离底部200px时触发加载请求 if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent - 200 && !_isLoading && _hasMore) { _loadData(); } } // 模拟接口请求,实际项目替换为真实网络请求 Future<void> _loadData() async { if (_isLoading) return; setState(() { _isLoading = true; }); await Future.delayed(const Duration(seconds: 1)); List<String> newData = List.generate(_pageSize, (index) { return "第${_currentPage}页 - 第${index + 1}条数据"; }); setState(() { _dataList.addAll(newData); _currentPage++; _isLoading = false; // 模拟加载5页后无更多数据 if (_currentPage > 5) { _hasMore = false; } }); } Widget _buildLoadMoreFooter() { if (!_hasMore) { return const Padding( padding: EdgeInsets.symmetric(vertical: 16), child: Center(child: Text('已加载全部数据')), ); } return _isLoading ? const Padding( padding: EdgeInsets.symmetric(vertical: 16), child: Center(child: CircularProgressIndicator()), ) : const SizedBox.shrink(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('分页加载示例')), body: ListView.builder( controller: _scrollController, itemCount: _dataList.length + 1, // +1 对应加载更多的footer itemBuilder: (context, index) { if (index == _dataList.length) { return _buildLoadMoreFooter(); } return ListTile( title: Text(_dataList[index]), ); }, ), ); } }
关键细节说明
- 滚动监听逻辑:设置200px的提前触发距离,避免用户滚动到底部才开始加载的等待感
- 状态校验:
_isLoading防止同一时间重复发起请求,_hasMore避免无数据时继续请求 - 列表构建:
itemCount包含数据量+footer,最后一个位置显示加载状态或无数据提示 - 请求兼容:示例用延迟模拟接口,实际项目中需替换为真实网络请求,并添加异常处理逻辑
实现效果示例

内容的提问来源于stack exchange,提问作者shirisha siri
相关产品推荐
相关产品推荐

