You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

列表视图分页异常:返回页面数据重复,滚动监听逻辑重复触发

分页重复数据与滚动监听器重复触发问题

首次打开页面时分页功能正常,但切换到其他页面再返回后,页码被重复处理,导致出现重复数据。排查发现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 16:57:14