Flutter结合Firebase:比对List取共有值并存入Firebase,intersection()无返回怎么办
现有代码无法得到正确交集结果的核心原因
- 变量作用域遮蔽导致数据未赋值。你在两个异步查询方法内部重新声明了和类成员同名的局部变量
followersList、followingList,方法内的所有数据添加操作都是对局部变量生效,类的成员变量始终没有被实际赋值,保持初始的null状态。 - Set交集的匹配逻辑不匹配。Dart中Set判断两个元素是否相等,默认使用对象的
==方法和hashCode实现。如果Users类没有重写这两个方法,哪怕两个对象存了完全相同的ID,因为是不同的内存实例,会被Set判定为完全不同的元素,最终交集计算结果为空。
针对需求的最优实现方案
整个逻辑围绕“按用户ID匹配共有关系”的核心目标设计,规避对象相等判断的坑,同时优化全链路性能:
- 并发拉取关注、粉丝两个用户列表,减少接口等待耗时
- 提取列表中的用户ID生成Set,利用Set的O(1)存在性判断能力快速筛选共有用户,避免高复杂度的双重循环匹配
- 使用Firebase的批量写入能力存储最终的共有用户列表,降低多次网络请求的开销
修正后的完整代码实现:
List<Users> followingList; List<Users> followersList; // 初始化数据方法,解决之前的变量遮蔽问题 Future<void> initUserData() async { // 两个Firebase查询并发执行,减少总等待时长 final listResults = await Future.wait([ _getFollowersUsers(), _getFollowingUsers() ]); // 将返回的结果赋值给类成员变量 followersList = listResults[0]; followingList = listResults[1]; } // 计算共有用户列表的方法 List<Users> getFinalMutualList() { // 提前判空避免空指针异常 if (followingList == null || followersList == null) return []; // 生成关注用户的ID集合,Set的存在性判断时间复杂度为O(1) final followingIdSet = followingList.map((user) => user.id).toSet(); // 筛选出同时在粉丝列表、关注列表中存在的用户 return followersList .where((follower) => followingIdSet.contains(follower.id)) .toList(); } // 将共有用户存入Firebase新集合的实现 Future<void> saveMutualUsers(List<Users> mutualUsers) async { Firestore db = Firestore.instance; // 初始化目标集合的引用 CollectionReference mutualCollection = db .collection('mutualConnections') .document(_userId) .collection('userMutual'); // 使用批量写入,避免循环单条await导致的多次网络请求 WriteBatch batch = db.batch(); for (Users user in mutualUsers) { DocumentReference userDoc = mutualCollection.document(user.id); batch.setData(userDoc, { 'name': user.name, 'photoUrl': user.photoUrl, 'username': user.username, 'id': user.id, 'bio': user.bio }); } await batch.commit(); }
方案优势说明:
- 从逻辑上和“比对共有ID”的需求对齐,不需要为
Users类额外重写相等判断方法,彻底规避对象相等判断的隐形bug - 计算效率远高于直接比对整个对象的方式:提取ID做Set匹配的整体时间复杂度为O(n+m),比双重循环匹配、无效对象比对的性能高一个量级
- 全流程做了并发、批量优化,网络请求次数从串行的4次(拉关注、拉粉丝、N次单条写入)压缩到2次拉取+1次批量写入,在用户列表较大的场景下性能提升非常明显
内容的提问来源于stack exchange,提问作者TonyCrudor
相关产品推荐
相关产品推荐

