如何在Flutter的StreamBuilder中存储Firebase Cloud Messaging通知?
问题解决思路
一、循环未执行的原因及修复
你的循环for (var message in message.data)没触发,核心是两个问题:
message.data是Map<String, String>类型,直接遍历Map只会拿到key,且如果消息的data字段为空,循环自然不会执行。要遍历键值对,得用message.data.entries- 循环变量名
message和外层的RemoteMessage message重名,会导致变量覆盖,存在编译隐患
修复后的循环示例:
// 遍历消息的data字段键值对 for (var entry in message.data.entries) { print('Key: ${entry.key}, Value: ${entry.value}'); // 可将data内容添加到消息记录 messagesShow.add('${entry.key}: ${entry.value}'); }
二、存储所有通知的修复方案
你只能单次获取一条消息,是因为FirebaseMessaging.onMessage流每次收到推送只会触发一次(传递单条消息),且原代码中notifications的状态维护不当,导致旧消息丢失。
1. 正确维护通知列表状态
把通知列表改为StatefulWidget的状态变量,确保消息不会因组件重建丢失:
class _NotificationPageState extends State<NotificationPage> { // 用状态变量存储所有通知 final List<RemoteMessage> _notifications = []; late StreamSubscription<RemoteMessage> _messageSubscription; @override void initState() { super.initState(); // 监听FCM前台消息,添加到通知列表 _messageSubscription = FirebaseMessaging.onMessage.listen((RemoteMessage message) { setState(() { _notifications.add(message); }); _messageController.add('New Message'); }); } @override void dispose() { _messageSubscription.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('通知')), body: _notifications.isEmpty ? const Center(child: Text('暂无通知')) : ListView.builder( itemCount: _notifications.length, itemBuilder: (context, index) { final message = _notifications[index]; return Padding( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(message.notification?.title ?? '无标题'), const SizedBox(height: 10), Text(message.notification?.body ?? '无内容'), // 可选:展示消息的data字段内容 if (message.data.isNotEmpty) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 10), const Text('附加数据:', style: TextStyle(fontWeight: FontWeight.bold)), ...message.data.entries.map((entry) => Text('${entry.key}: ${entry.value}')), ], ), ], ), ); }, ), ); } }
2. 为什么不用原StreamBuilder?
原StreamBuilder的snapshot每次只包含当前收到的单条消息,无法直接维护历史消息列表。改用StreamSubscription手动监听并更新状态变量,能更可靠地存储所有通知。
3. 持久化通知(可选)
如果需要APP重启后保留通知,可使用shared_preferences或本地数据库(如Hive、sqflite)将通知列表序列化存储,初始化时再读取恢复。
内容的提问来源于stack exchange,提问作者Anurag Prasad
相关产品推荐
相关产品推荐

