Flutter ListView数据重复问题:如何对接口返回列表去重后正常渲染
Flutter 接口返回列表去重及ListView构建方案
你可以通过对接口返回的学习模块列表按唯一标识去重后再渲染列表,具体实现如下:
步骤1:定义Dart数据实体类
先将JSON结构映射为Dart实体类,方便后续操作:
class LearningModule { final int sequenceno; final String id; final String chapter; final String title; final String packageDescription; final List<int> ageLevel; final String pkgSequence; final Packagescors packagescors; LearningModule({ required this.sequenceno, required this.id, required this.chapter, required this.title, required this.packageDescription, required this.ageLevel, required this.pkgSequence, required this.packagescors, }); factory LearningModule.fromJson(Map<String, dynamic> json) { return LearningModule( sequenceno: json['sequenceno'] as int, id: json['_id'] as String, chapter: json['chapter'] as String, title: json['title'] as String, packageDescription: json['package_description'] as String, ageLevel: List<int>.from(json['age_level']), pkgSequence: json['pkg_sequence'] as String, packagescors: Packagescors.fromJson(json['packagescors']), ); } // 可选:重写==和hashCode用于对象去重 @override bool operator ==(Object other) => identical(this, other) || other is LearningModule && runtimeType == other.runtimeType && id == other.id; @override int get hashCode => id.hashCode; } class Packagescors { final List<int> score; final List<String> date; Packagescors({required this.score, required this.date}); factory Packagescors.fromJson(Map<String, dynamic> json) { return Packagescors( score: List<int>.from(json['score']), date: List<String>.from(json['date']), ); } }
步骤2:对原始列表去重
推荐两种常用的去重实现方式:
- 方式1:通过唯一标识临时集合去重(无需修改实体类)
你可以用Set存储已经出现过的学习模块唯一标识_id,遍历原始列表时只保留首次出现的项:
// rawList为接口解析后得到的原始LearningModule列表 List<LearningModule> rawList = (json['data']['items'] as List).map((e) => LearningModule.fromJson(e)).toList(); Set<String> existedIdSet = {}; List<LearningModule> uniqueList = []; for (var item in rawList) { if (!existedIdSet.contains(item.id)) { existedIdSet.add(item.id); uniqueList.add(item); } }
如果你的去重规则不是按_id,比如需要按chapter+title联合判定重复,只需将Set存储的内容改为${item.chapter}_${item.title}即可。
- 方式2:通过对象Set直接去重(需重写实体类的和hashCode)
如果你已经在实体类中重写了运算符和hashCode,直接通过Set转List即可完成去重:
List<LearningModule> uniqueList = rawList.toSet().toList();
步骤3:构建ListView
将去重后的uniqueList直接传入ListView的builder即可:
ListView.builder( padding: const EdgeInsets.all(16), itemCount: uniqueList.length, itemBuilder: (context, index) { final module = uniqueList[index]; return Card( child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('章节:${module.chapter}', style: const TextStyle(fontWeight: FontWeight.bold)), const SizedBox(height: 4), Text(module.title), const SizedBox(height: 4), Text(module.packageDescription, style: TextStyle(color: Colors.grey[600])), ], ), ), ); } )
注意:如果是分页拉取数据时出现重复,建议将去重逻辑放在每次新数据追加到本地列表之后执行,避免重复渲染。
内容的提问来源于stack exchange,提问作者Febin Johnson
相关产品推荐
相关产品推荐

