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

Flutter接收FCM通知时调用showDialog遇上下文缺失问题求助

解决FCM点击通知弹出AlertDialog的Context问题

你在main()函数中直接调用showDialog会报错,因为此时Widget树尚未构建完成,没有可用的BuildContext。以下是两种可行的解决方案:

方案一:使用全局NavigatorKey获取Context

通过定义全局的NavigatorState Key,可以在任何地方获取到可用的Context,无需依赖Widget的上下文。

  1. 在main.dart顶部定义全局Key:
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
  1. 在MaterialApp中绑定这个Key:
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: navigatorKey, // 绑定全局导航Key
      title: 'FCM Demo',
      home: const HomePage(),
    );
  }
}
  1. 修改FCM监听代码,使用全局Key的Context:
// 前台接收通知时弹出Dialog
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
  if (message.notification != null && navigatorKey.currentContext != null) {
    showDialog(
      context: navigatorKey.currentContext!,
      builder: (_) => AlertDialog(
        title: Text(message.notification!.title!),
        content: Text(message.notification!.body!),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(navigatorKey.currentContext!),
            child: const Text('关闭'),
          ),
        ],
      ),
    );
  }
});

// 后台点击通知打开应用时弹出Dialog
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
  if (message.notification != null && navigatorKey.currentContext != null) {
    showDialog(
      context: navigatorKey.currentContext!,
      builder: (_) => AlertDialog(
        title: Text(message.notification!.title!),
        content: Text(message.notification!.body!),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(navigatorKey.currentContext!),
            child: const Text('关闭'),
          ),
        ],
      ),
    );
  }
});

方案二:将FCM监听移至有Context的Widget内

把FCM的监听逻辑移到StatefulWidget的initState方法中,此时可以直接使用Widget的BuildContext。

  1. 修改MyApp为StatefulWidget,并在initState中设置FCM监听:
class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late FirebaseMessaging _messaging;

  @override
  void initState() {
    super.initState();
    _messaging = FirebaseMessaging.instance;
    _setupFCMListeners();
  }

  void _setupFCMListeners() {
    // 前台接收通知
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      if (message.notification != null) {
        showDialog(
          context: context,
          builder: (_) => AlertDialog(
            title: Text(message.notification!.title!),
            content: Text(message.notification!.body!),
            actions: [
              TextButton(
                onPressed: () => Navigator.pop(context),
                child: const Text('关闭'),
              ),
            ],
          ),
        );
      }
    });

    // 后台点击通知打开应用
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      if (message.notification != null) {
        showDialog(
          context: context,
          builder: (_) => AlertDialog(
            title: Text(message.notification!.title!),
            content: Text(message.notification!.body!),
            actions: [
              TextButton(
                onPressed: () => Navigator.pop(context),
                child: const Text('关闭'),
              ),
            ],
          ),
        );
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'FCM Demo',
      home: const HomePage(),
    );
  }
}
  1. 简化main()函数,移除原有的监听代码:
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  FirebaseMessaging messaging = FirebaseMessaging.instance;

  NotificationSettings settings = await messaging.requestPermission(
    alert: true,
    announcement: false,
    badge: true,
    carPlay: false,
    criticalAlert: false,
    provisional: false,
    sound: true,
  );

  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

  runApp(const MyApp());
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 21:30:54