Flutter异步分页过滤异常:循环内currentPage变量未实时更新
问题原因分析
- 异步操作未等待:
pageGetter是异步函数,但你在filterByName的循环里直接调用却未使用await,导致所有分页请求几乎同时发起,过滤逻辑会在请求完成前就执行,此时currentPage还未更新,所以一直复用初始的第1页数据。 - 参数传递错误:
pageGetter里的x是值传递,函数内部给x赋值不会影响外部的currentPage变量,等于没有实际更新全局状态。 - 同步循环与异步请求冲突:循环会快速执行完42次,但异步请求的完成顺序不确定,
currentPage最终会被最后完成的请求覆盖,导致过滤结果混乱。
修复代码
第一步:修复pageGetter函数
直接操作全局的currentPage,移除无用的x参数,同时返回获取到的页面数据:
Future<CharacterPage?> pageGetter(int i) async { Dio dio = Dio(); try { var pageData = await dio.get('https://rickandmortyapi.com/api/character?page=$i'); if (pageData.statusCode == HttpStatus.ok) { currentPage = CharacterPage.fromJson(pageData.data); if (mounted) { setState(() {}); } return currentPage; } } catch (e) { print('请求第$i页失败: $e'); } return null; }
第二步:重构filterByName为异步函数
改成逐页等待请求完成后再过滤,确保每一页的数据都正确获取后再处理:
Future<List<Character>> filterByName() async { filteredByName.clear(); // 先获取第1页,拿到总页数 final firstPage = await pageGetter(1); if (firstPage == null) return filteredByName; int totalPages = firstPage.info.pages; // 遍历所有页码,逐页处理 for (int pageNum = 1; pageNum <= totalPages; pageNum++) { final currentPage = await pageGetter(pageNum); if (currentPage == null) continue; // 过滤当前页的结果 for (var character in currentPage.results) { if (character.name.contains(nameFilterText)) { filteredByName.add(character); } } // 可选:每处理一页就更新UI,让用户看到实时进度 if (mounted) { setState(() {}); } } return filteredByName; }
第三步:修改按钮的点击事件
因为filterByName现在是异步函数,点击事件也要用async/await:
TextButton( onPressed: () async { filteredByName = []; results = await filterByName(); if (mounted) { setState(() {}); } }, child: const Text("Search") )
额外优化建议
- 添加加载状态,比如显示
CircularProgressIndicator,避免用户重复点击搜索按钮。 - 对
nameFilterText做非空判断,避免空字符串过滤出所有结果。 - 加入请求取消逻辑,用户再次点击搜索时取消之前的请求,避免资源浪费。
内容的提问来源于stack exchange,提问作者Doğan Erarslan
相关产品推荐
相关产品推荐

