Flutter 如何实现PageView滑动时加载分3条一组的列表新数据
核心问题定位
- PageView的itemBuilder未绑定组件自带的页码参数,始终传入全局维护的
addToIndex值,无论滑动到第几页,传入的列表偏移量固定,导致所有页面渲染相同位置的3条数据 - PageView总页数计算逻辑错误:当前设置
itemCount: questions.length,但每个PageView页面固定承载3条问题,应按总数据量折算总页数,否则会出现大量无效页面 - _onPageChanged的全局变量累加逻辑存在缺陷:通过手动给
addToIndex叠加3的方式计算偏移量,当用户回退页码时,累加值会计算错误,完全不需要额外维护全局偏移变量 - 未做数组越界保护:硬编码ListView的
itemCount:3,当剩余有效数据不足3条时(比如总20条数据的最后一页仅存2条),会触发索引越界异常
修正实现方案
- 移除全局变量
int addToIndex=0,通过PageView自带的页码参数直接计算列表偏移量,消除手动维护状态的误差 - 调整PageView的总页数计算规则,按单页3条的承载量向上取整
- 为ListView增加越界保护,动态计算单页可展示的有效条目数
- 调整数据拉取逻辑,累计加载直到达到20条的目标值
修正后PageView代码
import 'dart:math' as math; // 需引入math库用于取整计算 PageView.builder( controller: _pageController, onPageChanged: (index) { // 仅保留页码变化需要的自定义逻辑,无需手动修改偏移量 }, // 总页数向上取整,例如20条数据对应7个PageView页面 itemCount: (questions.length / 3).ceil(), itemBuilder: (BuildContext context, int index) { // 直接通过当前页码计算数据偏移量,替代原有全局addToIndex int dataOffset = index * 3; return _pageView(dataOffset); }, ),
修正后_pageView方法代码
Widget _pageView(int dataOffset) { return Column( children: [ Expanded( child: Padding( padding: const EdgeInsets.only(top: 15.0), child: Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(10))), elevation: 4, child: ListView.builder( itemBuilder: (BuildContext ctx, int index) { int realDataIndex = index + dataOffset; return listItem( ctx, index, "User " + questions[realDataIndex].user.userName, _timeAgo(realDataIndex), questions[realDataIndex].id, questionTitle: questions[realDataIndex].title); }, // 动态计算当前页有效条目数,避免越界 itemCount: math.min(3, questions.length - dataOffset), ), ), ), ), ], ); }
数据加载逻辑调整
_getData() async { ResourceFetchingAuthority _resourceFetchingAuthority = ResourceFetchingAuthority( configuration: ResourceFetchingConfiguration( maxReturnedResourcesForFirstPage: 12, // 配置后续分页拉取参数,直到总数据量达到20条停止 ... ResourceFetchingResult unansweredQuestionsResult = await _resourceFetchingAuthority.fetchResources(); List<QuestionViewV1> newData = unansweredQuestionsResult.resources.cast<QuestionViewV1>(); setState(() { // 累计追加数据,不超过20条的目标值 questions.addAll(newData.take(20 - questions.length)); }); }
内容的提问来源于stack exchange,提问作者Alex Apps
相关产品推荐
相关产品推荐

