Flutter Firestore:解决同一账号多设备同时点赞重复计数问题
解决Firestore跨设备重复点赞问题
你的问题核心在于非原子性的“读-判断-写”流程:当两台设备同时读取到isLike=false时,都会执行点赞操作,导致计数重复。要彻底解决这个问题,必须用Firestore的**事务(Transaction)**来保证整个操作的原子性——要么所有步骤都成功,要么全部不执行,从根源避免并发冲突。
修正后的代码实现
await db.runTransaction((transaction) async { // 1. 在事务中同时获取用户文档和目标物品文档 final userDoc = db.collection('users').doc(user.uid); final itemDoc = db.collection('items').doc('item'); final userSnapshot = await transaction.get(userDoc); final itemSnapshot = await transaction.get(itemDoc); // 2. 检查用户是否未点赞 if (!userSnapshot.data()!['isLike']) { // 3. 原子性更新:同时修改用户点赞状态和物品点赞数 transaction.update(userDoc, {'isLike': true}); transaction.update(itemDoc, { 'likeCount': FieldValue.increment(1) }); } });
关键说明
- 事务的原子性:Firestore会确保事务中的所有读写操作作为一个整体执行,并发请求时只有一个能成功修改数据,其他请求会自动重试(或失败),不会出现重复计数。
- 跨文档事务支持:Firestore允许在单个事务中操作多个文档,刚好匹配你需要同时更新用户状态和物品计数的场景。
- 重试机制:如果事务因为并发冲突失败,Firestore会自动重试(默认最多5次),无需额外处理逻辑。
额外优化建议
- 可以在本地缓存用户的点赞状态,减少不必要的Firestore读取,提升响应速度,但核心的并发控制仍需依赖事务。
- 如果需要支持取消点赞,同样要把“取消点赞+计数减1”的逻辑放在事务中,保持操作的原子性。
内容的提问来源于stack exchange,提问作者Andy Li
相关产品推荐
相关产品推荐

