列表视图分页异常:返回页面数据重复,滚动监听逻辑重复触发
分页重复数据与滚动监听器重复触发问题
首次打开页面时分页功能正常,但切换到其他页面再返回后,页码被重复处理,导致出现重复数据。排查发现if (_sc.position.pixels == _sc.position.maxScrollExtent)语句会循环执行,对应的打印日志被调用两次。
相关代码(List.dart)
@override void initState() { print('current page value init: ${currentPage}'); checkId = Provider.of<LoginProvider>(context, listen: false).id; categoryCheck = Provider.of<LoginProvider>(context, listen: false).category; if (categoryCheck != null) { if (Provider.of<OpenProjectProvider>(context, listen: false) .items .isEmpty) { myfuture = Provider.of<OpenProjectProvider>(context, listen: false) .readinboxNotification(checkId, currentPage); } } else { if (Provider.of<OpenProjectProvider>(context, listen: false) .items .isEmpty) { myfuture = Provider.of<OpenProjectProvider>(context, listen: false) .readinboxNotificationInd(checkId, currentPage); } } super.initState(); // 根据我的判断,下面这段代码是问题根源 _sc.addListener(() { print('current page getmoredata: ${currentPage}'); if (_sc.position.pixels == _sc.position.maxScrollExtent) { // 这个条件会多次触发 _getMoreData(currentPage++); } }); }
打印输出
2 current page getmoredata: 1 67 current page getmoredata: 2
解决方法
1. 避免重复添加滚动监听器
页面切换返回时,initState会重新执行,导致重复绑定滚动监听器,同一个滚动事件会触发多次回调。需在页面销毁时移除监听器:
@override void dispose() { _sc.removeListener(_scrollListener); super.dispose(); } // 将监听器逻辑抽为独立方法 void _scrollListener() { print('current page getmoredata: ${currentPage}'); if (_sc.position.pixels == _sc.position.maxScrollExtent) { _getMoreData(currentPage++); } } // 在initState中绑定监听器 @override void initState() { // ... 原有初始化代码 ... _sc.addListener(_scrollListener); super.initState(); }
2. 添加加载状态锁,防止重复请求
滚动到底部时,若上一次分页请求还未完成,直接阻止新请求触发,避免重复数据:
bool _isLoading = false; void _scrollListener() { if (_isLoading) return; // 正在加载时直接返回 if (_sc.position.pixels == _sc.position.maxScrollExtent) { _isLoading = true; _getMoreData(currentPage++).then((_) { _isLoading = false; // 请求完成后解锁 }).catchError((_) { _isLoading = false; // 出错也要解锁 currentPage--; // 页码回滚,避免下次请求错误页码 }); } }
3. 重置页码初始值
页面返回重新初始化时,确保currentPage从初始值(比如1)开始,避免页码累加错误:
@override void initState() { currentPage = 1; // 强制重置为初始页码 // ... 其他初始化代码 ... }
4. 优化滚动到底部的判断逻辑
直接判断pixels == maxScrollExtent可能因滚动惯性或精度问题多次触发,改用更可靠的判断方式:
void _scrollListener() { if (_isLoading) return; // 判断是否滚动到底部(非顶部边缘) if (_sc.position.atEdge && _sc.position.pixels != 0) { _isLoading = true; _getMoreData(currentPage++).then((_) { _isLoading = false; }).catchError((e) { _isLoading = false; currentPage--; }); } }
内容的提问来源于stack exchange,提问作者akm
相关产品推荐
相关产品推荐

