Flutter 中 Firebase Messaging 如何订阅 Firestore 子集合实现变动通知
解决方案
核心逻辑说明
你不需要直接在Flutter端订阅Firestore子集合来触发通知推送,只需要调整云函数的推送规则,配合Flutter端订阅对应FCM主题即可实现需求:每个用户仅接收自己账号下messages子集合变动的推送通知。
1. 调整Firebase Functions代码
你当前的代码会把所有用户的新消息都推送到全局users主题,会导致所有订阅该主题的用户收到全部用户的消息,不符合单用户接收自有通知的要求。我们通过路径参数拿到触发事件的用户ID,为每个用户生成独立的专属推送主题即可:
functions.firestore .document("users/{userId}/messages/{messageId}") .onCreate((snapshot, context) => { // 从触发路径中获取对应用户ID const targetUserId = context.params.userId; const messageData = snapshot.data(); // 推送到当前用户的专属主题,前缀user_用于避免和其他业务主题冲突 return admin.messaging().sendToTopic(`user_${targetUserId}`, { notification: { title: messageData.username, body: messageData.text, clickAction: "FLUTTER_NOTIFICATION_CLICK", }, }); });
2. Flutter端订阅逻辑
在用户登录成功、拿到自己的用户ID之后,订阅和自己用户ID绑定的专属主题即可:
import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:firebase_auth/firebase_auth.dart'; // 用户登录成功后调用该方法完成订阅 Future<void> subscribeToUserMessageNotice() async { final currentUser = FirebaseAuth.instance.currentUser; if (currentUser == null) return; // 主题命名和云函数保持完全一致 await FirebaseMessaging.instance.subscribeToTopic('user_${currentUser.uid}'); } // 用户退出登录时调用该方法取消订阅,避免收到后续其他账号的通知 Future<void> unsubscribeFromUserMessageNotice() async { final currentUser = FirebaseAuth.instance.currentUser; if (currentUser == null) return; await FirebaseMessaging.instance.unsubscribeFromTopic('user_${currentUser.uid}'); }
可选优化
如果你的推送对安全性要求较高,担心用户恶意订阅其他用户的主题,可以改用FCM令牌推送方案:在用户的Firestore文档中存储用户设备的FCM令牌,云函数触发时直接查询对应用户的令牌列表,调用sendToDevice方法推送即可。
内容的提问来源于stack exchange,提问作者Flutter Dev
相关产品推荐
相关产品推荐

