如何使用StreamController实现Flutter推送通知的页面实时更新
前置准备
- 先完成firebase_messaging的基础配置,在pubspec.yaml中引入依赖:
firebase_messaging: ^14.6.1(版本可根据项目适配情况调整)
实现步骤
- 第一步:创建全局广播Stream控制器,用于跨页面传递FCM推送数据
import 'dart:async'; // 全局单例控制器,broadcast类型支持多个页面同时监听 final StreamController<Map<String, dynamic>> fcmMessageStream = StreamController<Map<String, dynamic>>.broadcast();
- 第二步:在FCM的全场景回调中注入推送数据到Stream
需要覆盖前台接收、后台点击通知打开应用、应用终止后点击通知打开应用三种场景:
import 'package:firebase_messaging/firebase_messaging.dart'; // 应用初始化时调用这段配置 void initFCMListener() async { // 1. 前台收到推送时触发 FirebaseMessaging.onMessage.listen((RemoteMessage message) { fcmMessageStream.add(message.data); // 可补充前台通知弹窗逻辑 }); // 2. 后台挂起状态下点击通知打开应用时触发 FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { fcmMessageStream.add(message.data); }); // 3. 应用完全终止状态下点击通知打开应用时触发 RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage(); if (initialMessage != null) { fcmMessageStream.add(initialMessage.data); } }
- 第三步:页面层监听Stream更新UI
推荐直接使用StreamBuilder组件,框架会自动处理监听的生命周期:
@override Widget build(BuildContext context) { return StreamBuilder<Map<String, dynamic>>( stream: fcmMessageStream.stream, builder: (context, snapshot) { if (snapshot.hasData) { final pushData = snapshot.data!; // 此处根据业务需求更新UI,比如刷新消息列表、跳转指定页面 return Text("新推送内容:${pushData['content'] ?? '无内容'}"); } return const Text("暂无新推送"); }, ); }
注意事项
- 如果手动调用
stream.listen()做自定义逻辑,需要保存返回的StreamSubscription实例,在页面dispose生命周期中调用cancel()方法释放资源,避免内存泄漏;使用StreamBuilder无需额外处理,框架会自动销毁监听。 - 确保全局只有一个
fcmMessageStream实例,FCM回调和页面监听必须使用同一个控制器才能正常接收数据。 - 如果需要新监听者加入时能获取到最近一次的推送数据,可以引入rxdart包,用
BehaviorSubject替代默认的StreamController。
内容的提问来源于stack exchange,提问作者Shammah
相关产品推荐
相关产品推荐

