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

Flutter分页加载更多出现重复数据,求代码问题排查

问题分析与修复方案

嘿,我一眼就看到问题所在了——你的页码递增逻辑确实出了小问题,而且还有几个细节可以优化,让我慢慢给你说:

1. 核心错误:页码自增写法无效

你在_getAllNews方法里写的:

currentPage = currentPage++;

这是典型的自增运算符使用错误!currentPage++是后自增,它的执行逻辑是:先返回当前的currentPage值,再把变量自身加1。所以这行代码相当于把当前的页码值重新赋值给自己,完全没有实现“页码+1”的效果!这就导致每次加载更多时,你请求的都是同一页的数据,自然会出现重复内容。

修复方式:直接改成以下两种写法之一即可:

currentPage++;
// 或者
currentPage += 1;

2. 额外问题:重复添加滚动监听器

你在initState中调用handleNext(),而handleNext()里每次执行都会给scrollController添加一个新的滚动监听器。这会导致滚动到底部时,多个监听器同时触发_getAllNews请求,不仅浪费服务器资源,还会加重重复数据的问题。

修复方式:把监听器的初始化直接放到initState里,避免重复添加:

@override
void initState() {
  _getAllNews(currentPage);
  // 直接在这里添加监听器
  scrollController.addListener(() async {
    if (!isLoading && !hasReachedEnd && scrollController.position.maxScrollExtent == scrollController.position.pixels) {
      _getAllNews(currentPage);
    }
  });
  super.initState();
}
// 删掉原来的handleNext方法

3. 优化点:避免重复/无效请求

当页面已经在加载数据,或者已经加载到最后一页时,应该禁止再次触发请求。可以在触发_getAllNews前添加判断条件,避免不必要的请求:

scrollController.addListener(() async {
  // 只有当不在加载、没到最后一页,且滚动到底部时才触发请求
  if (!isLoading && !hasReachedEnd && scrollController.position.maxScrollExtent == scrollController.position.pixels) {
    _getAllNews(currentPage);
  }
});

同时,在_getAllNews里,还要判断返回的数据是否为空,来标记hasReachedEnd:

_getAllNews(page) async {
  setState(() {
    isLoading = true;
  });
  var articles = await http.get(Uri.parse(
      "https://pkbhai.com/myprojects/kids-stories/api/all-stories?page=${page}"));
  var result = json.decode(articles.body);
  print(result);
  
  // 判断返回的数据是否为空,标记是否到最后一页
  if (result['data'].isEmpty) {
    setState(() {
      hasReachedEnd = true;
      isLoading = false;
    });
    return;
  }

  List<NewsModel> newNews = [];
  result['data'].forEach((data) {
    var news = NewsModel();
    news.id = data["id"];
    news.articleTitle = data["name"];
    newNews.add(news);
  });

  if (mounted) {
    setState(() {
      _newsList.addAll(newNews); // 用addAll比循环add更高效
      isLoading = false;
      currentPage++; // 这里修正自增逻辑
    });
  }
}

修正后的完整代码

class Tedd extends StatefulWidget {
  @override
  _TeddState createState() => _TeddState();
}

class _TeddState extends State<Tedd> {
  List<NewsModel> _newsList = [];
  bool isLoading = true;
  int currentPage = 1;
  bool hasReachedEnd = false;
  ScrollController scrollController = ScrollController();

  _getAllNews(page) async {
    setState(() {
      isLoading = true;
    });
    var articles = await http.get(Uri.parse(
        "https://pkbhai.com/myprojects/kids-stories/api/all-stories?page=${page}"));
    var result = json.decode(articles.body);
    print(result);

    if (result['data'].isEmpty) {
      setState(() {
        hasReachedEnd = true;
        isLoading = false;
      });
      return;
    }

    List<NewsModel> newNews = [];
    result['data'].forEach((data) {
      var news = NewsModel();
      news.id = data["id"];
      news.articleTitle = data["name"];
      newNews.add(news);
    });

    if (mounted) {
      setState(() {
        _newsList.addAll(newNews);
        isLoading = false;
        currentPage++; // 修正后的自增逻辑
      });
    }
  }

  @override
  void initState() {
    _getAllNews(currentPage);
    // 直接添加滚动监听器,避免重复添加
    scrollController.addListener(() async {
      if (!isLoading && !hasReachedEnd && scrollController.position.maxScrollExtent == scrollController.position.pixels) {
        _getAllNews(currentPage);
      }
    });
    super.initState();
  }

  @override
  void dispose() {
    // 记得销毁控制器,避免内存泄漏
    scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        controller: scrollController,
        itemCount: _newsList.length + (isLoading ? 1 : 0),
        itemBuilder: (context, index) {
          if (index == _newsList.length) {
            return Center(
              child: CircularProgressIndicator(),
            );
          }
          return Container(
              height: 150, child: Text(_newsList[index].articleTitle!));
        },
      ),
    );
  }
}

内容的提问来源于stack exchange,提问作者Pramod Yadav

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 17:30:41