Flutter+Firestore社交APP关注列表ID比对异常问题求解
问题根因
你代码的核心错误是使用了全局单一变量isFollowedByMe存储关注状态:
followingList.any(check)的逻辑是判断「当前打开的主页的粉丝列表中是否存在任意一个用户是你关注的」,只要列表里有1个你关注的用户,这个全局变量就会被设为true,所有列表项都会复用这个状态,自然所有用户都显示「取消关注」。- 你需要的是给每个列表项单独判断对应用户ID是否在你的关注列表里,而不是给整个列表只判断一次。
修复方案
第一步:优化查询逻辑,把我的关注列表存为Set提升查询效率
首先修改checkfollowers方法,不用全局的isFollowedByMe,而是把我的关注列表存为Set供列表项查询:
// 在ProfileState里新增变量 Set<String> myFollowingSet = {}; checkfollowers(BuildContext context, String? id) async { final auth = Provider.of<AuthState>(context, listen: false); myFollowingSet = {}; // 先清空旧数据 try { final QuerySnapshot following = await _firestore .collection('following') .doc(auth.getCurrentUser.uid) .collection('userFollowing') .get(); // 把我的关注列表存为Set,contains查询时间复杂度是O(1),比List的O(n)快很多 for (var element in following.docs) { myFollowingSet.add(element.id); } notifyListeners(); print(myFollowingSet); } catch (err) { print(err.toString() + 'this error is coming from profileState'); } }
第二步:修改列表项的状态判断逻辑
渲染每个用户项的时候,单独判断当前用户的ID是否在myFollowingSet里,不要用全局的isFollowedByMe:
userComponent(UserModel? model, BuildContext context) { final profileState = Provider.of<ProfileState>(context); final auth = Provider.of<AuthState>(context); // 新增:单独判断当前项的用户是否被我关注 bool isCurrentUserFollowed = profileState.myFollowingSet.contains(model?.userId); return Container( margin: EdgeInsets.symmetric(horizontal: 10), padding: EdgeInsets.only(top: 10, bottom: 10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GestureDetector( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => ProfilePage(profileId: '${model?.userId}'), ), ); }, child: Row( children: [ Container( width: 60, height: 60, child: CircleAvatar( radius: 50, backgroundImage: NetworkImage('${model?.profilePic}'), ), ), SizedBox(width: 10), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text('${model?.userName}', style: TextStyle( color: Colors.black, fontWeight: FontWeight.w500)), SizedBox( height: 5, ), Text( '${model?.displayName}', style: TextStyle( color: Colors.grey[500], ), ), ], ) ], ), ), auth.getCurrentUser.uid == model?.userId ? Container() : GestureDetector( onTap: () { if (auth.getCurrentUser.uid == model?.userId) { print('you can not follow your self'); } else if (isCurrentUserFollowed) { // 取消关注后要把ID从Set里移除 profileState.myFollowingSet.remove(model?.userId); profileState.handleUnFollow(context, model?.userId); profileState.notifyListeners(); } else { // 关注后要把ID加到Set里 profileState.myFollowingSet.add(model?.userId); profileState.handleFollow(context, model?.userId); profileState.notifyListeners(); } }, child: AnimatedContainer( height: 35, width: 110, duration: Duration(milliseconds: 300), decoration: BoxDecoration( color: isCurrentUserFollowed ? AppColors.white : AppColors.pinkaccent, borderRadius: BorderRadius.circular(5), border: Border.all( color: Colors.grey.shade700, ), ), child: Center( child: Text( isCurrentUserFollowed ? 'UnFollow' : 'Follow', style: TextStyle( color: isCurrentUserFollowed ? Colors.black : Colors.white), ), ), ), ) ], ), ); }
额外优化建议
- 可以把
myFollowingSet做本地缓存,不用每次进入粉丝列表都重新查询,只有关注/取消操作的时候更新缓存即可,减少数据库请求。 - 如果粉丝列表数据量很大,用Stream实时监听我的关注列表变动,不需要手动刷新状态。
内容的提问来源于stack exchange,提问作者Jovane Mullings
相关产品推荐
相关产品推荐

