Web端Firebase Messaging后台isolate如何向主应用传递数据
实现Firebase Messaging后台Isolate与主应用的数据通信
核心思路
利用Flutter官方提供的IsolateNameServer工具实现跨Isolate的端口注册与查找,不需要依赖持久化存储,全平台(含Web)原生支持,可直接在后台回调的顶层函数中向主应用实时发送数据。
具体实现步骤
1. 主应用侧注册通信端口
在应用启动时创建ReceivePort监听消息,同时将对应的SendPort注册到IsolateNameServer,使用固定的唯一名称标识,供后台Isolate查找:
import 'dart:isolate'; import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/services.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); // 初始化跨Isolate通信端口 final ReceivePort backgroundMsgPort = ReceivePort(); IsolateNameServer.registerPortWithName(backgroundMsgPort.sendPort, 'firebase_background_msg_port'); // 监听后台Isolate发送的推送数据 backgroundMsgPort.listen((dynamic data) { // 此处处理收到的后台推送数据,data为序列化后的消息内容 if (data is Map) { final RemoteMessage msg = RemoteMessage.fromMap(Map<String, dynamic>.from(data)); // 执行业务逻辑:更新状态、弹通知、数据上报等 } }); // 注册后台消息回调 FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler); runApp(const MyApp()); }
2. 后台回调函数中发送数据到主应用
在onBackgroundMessage对应的顶层处理函数中,查找主应用注册的SendPort,将消息序列化后发送:
@pragma('vm:entry-point') Future<void> backgroundMessageHandler(RemoteMessage message) async { await Firebase.initializeApp(); // 查找主应用注册的通信端口 final SendPort? mainPort = IsolateNameServer.lookupPortByName('firebase_background_msg_port'); // 端口存在则发送数据,主应用已被系统杀死时端口会自动注销,此时发送逻辑会跳过 if (mainPort != null) { mainPort.send(message.toMap()); } }
注意事项
- 跨Isolate发送的数据必须是可序列化的基础类型、Map或List,禁止直接发送未序列化的对象,建议先调用
RemoteMessage.toMap()序列化后再传输 - 顶层后台处理函数必须添加
@pragma('vm:entry-point')注解,避免release版本打包时被摇树优化导致功能失效 - 如果需要兼容主应用已被杀死的场景,可以使用
shared_preferences做临时缓存,该库在Web平台基于localStorage实现,不属于被禁止的sqlite/文件存储范畴
内容的提问来源于stack exchange,提问作者yoni keren
相关产品推荐
相关产品推荐

