Flutter接收FCM通知时调用showDialog遇上下文缺失问题求助
解决FCM点击通知弹出AlertDialog的Context问题
你在main()函数中直接调用showDialog会报错,因为此时Widget树尚未构建完成,没有可用的BuildContext。以下是两种可行的解决方案:
方案一:使用全局NavigatorKey获取Context
通过定义全局的NavigatorState Key,可以在任何地方获取到可用的Context,无需依赖Widget的上下文。
- 在
main.dart顶部定义全局Key:
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
- 在
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(), ); } }
- 修改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。
- 修改
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(), ); } }
- 简化
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
相关产品推荐
相关产品推荐

