You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter应用分离Firebase Cloud Messaging至独立文件后无法获取通知数据

问题分析与解决方案

首先,咱们来拆解下你遇到的两个核心问题:

  1. initState里直接用await是非法的:initState方法不能标记为async,这会违反Flutter框架的生命周期规则。
  2. 通知数据无法传递的本质原因:你的initialise方法返回的initMessage是初始默认值,因为_fcm.configure里的onMessage/onLaunch/onResume都是异步回调——当这些回调触发并给initMessage赋值时,initialise早就已经返回了初始字符串,所以main.dart里拿不到真实的通知数据。

另外那个Fatal: failed to find callback是旧版FCM SDK的小bug,升级SDK版本大概率能解决,但这不是影响你获取数据的核心问题。

下面是具体的修复方案,我们用Stream来实现通知数据的实时传递,这是处理异步回调数据的标准方式:

1. 重构push_notification_service.dart

我们添加一个StreamController来广播通知数据,让外部可以监听数据变化:

import 'dart:io';
import 'dart:async';
import 'package:firebase_messaging/firebase_messaging.dart';

class PushNotificationService {
  final FirebaseMessaging _fcm;
  final StreamController<String> _notificationController = StreamController<String>.broadcast();

  // 对外暴露Stream,供外部监听通知标题
  Stream<String> get notificationTitleStream => _notificationController.stream;

  PushNotificationService(this._fcm);

  Future<void> initialise() async {
    if (Platform.isIOS) {
      await _fcm.requestNotificationPermissions(const IosNotificationSettings());
    }

    _fcm.configure(
      onMessage: (Map<String, dynamic> message) async {
        print("Message -Foreground- received: $message");
        final title = message['notification']['title'];
        _notificationController.add(title);
      },
      onLaunch: (Map<String, dynamic> message) async {
        print("Message -Closed- received: $message");
        final title = message['notification']['title'];
        _notificationController.add(title);
      },
      onResume: (Map<String, dynamic> message) async {
        print("Message -Background- received: $message");
        final title = message['notification']['title'];
        _notificationController.add(title);
      },
    );

    // 可选:处理冷启动时的初始通知
    final initialMessage = await _fcm.getInitialMessage();
    if (initialMessage != null) {
      final title = initialMessage['notification']['title'];
      _notificationController.add(title);
    }
  }

  // 页面销毁时关闭StreamController,避免内存泄漏
  void dispose() {
    _notificationController.close();
  }
}

2. 修改main.dart监听通知数据

现在我们在initState中初始化服务,并监听Stream来更新title:

import 'package:flutter/material.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import './push_notification_service.dart';

void main() => runApp(const MyApp());

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final FirebaseMessaging _fcm = FirebaseMessaging.instance; // 新版FCM推荐写法,旧版可改回FirebaseMessaging()
  late PushNotificationService _notificationService;
  String title = "Notif Title";
  String helperText = "Notif Text";
  StreamSubscription? _notificationSubscription;

  @override
  void initState() {
    super.initState();
    _initNotificationService();
  }

  // 用单独的异步函数包裹初始化逻辑,避免在initState里直接用async
  void _initNotificationService() async {
    _notificationService = PushNotificationService(_fcm);
    await _notificationService.initialise();

    // 监听通知标题变化,实时更新UI
    _notificationSubscription = _notificationService.notificationTitleStream.listen((newTitle) {
      setState(() {
        title = newTitle;
      });
    });
  }

  @override
  void dispose() {
    _notificationSubscription?.cancel();
    _notificationService.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(child: Text(title)),
      ),
    );
  }
}

额外说明

  • 我把FirebaseMessaging _fcm = FirebaseMessaging();改成了FirebaseMessaging.instance,这是FCM最新版本的推荐写法,如果你用的是旧版SDK,可以改回原来的写法。
  • 新增了dispose方法来关闭Stream和取消订阅,这是避免内存泄漏的关键步骤。
  • 加入了getInitialMessage的处理,确保冷启动点击通知时也能获取到通知数据。

这样修改后,无论是前台、后台还是冷启动收到通知,title变量都会实时更新并刷新UI,你之前遇到的问题就解决啦。

内容的提问来源于stack exchange,提问作者usersina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 17:52:30