Flutter - 如何获取当前上下文?

Flutter - how to get current context?

我正在使用 Firebase 云消息传递进行通知,我想在我进入应用程序时收到通知后显示一个对话框或快餐栏,我的问题是我正在我的顶部初始化 firebase 配置小部件树(应用程序启动后的启动画面)

_fireBaseMessaging.configure(
  onMessage: (Map<String, dynamic> message) async {
    dynamic data = message['data'];
    ................ // Adding a snackbar/alertdialog here doesn't work
  },
);

显然,如果我设置对话框或小吃栏,它不会显示,因为我需要我当前页面的上下文,有什么方法可以获取当前上下文吗?

我也试过将它放入启动画面的构建小部件中,但是当我在另一个页面上时,对话框仍然没有显示。

 @override
  Widget build(BuildContext context) {
    _fireBaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) async {
        print("onMessage: $message");
        dynamic data = message['data'];
        if (data['id'] == '1') {
          newPro = true;
        } else if (data['id'] == '2') {
          print("THIS WORKS!!!");
          showDialog(
              context: context,
              builder: (context) => AlertDialog(
                    content: ListTile(
                      title: Text("TEST"),
                      subtitle: Text("TEST"),
                    ),
                    actions: <Widget>[
                      FlatButton(
                        child: Text("OK"),
                        onPressed: () => Navigator.pop(context),
                      )
                    ],
                  ));
        }
      },
    );

在树中第一个小部件的构建方法中进行初始化!通常它称为 App 小部件,它是 StateLess StateFull 小部件,在构建方法中您可以访问 BuildContext

我最终使用了覆盖支持:

https://pub.dev/packages/overlay_support

它基本上是在我的树的最开始调用的,就像在 main.dart 中包装提供者一样,它的工作就像一个魅力,没有其他任何工作! 还有一个教程对我帮助很大:

https://medium.com/flutter-community/in-app-notifications-in-flutter-9c1e92ea10b3

我遇到了完全相同的问题,但我在 GitHub 上找到了一个很棒的帖子。基本上,您可以创建一个 navigatorKey 并将其传递给 MaterialApp,然后使用该 navigatorKey 更改路线。

在这个线程中查看如何:https://github.com/brianegan/flutter_redux/issues/5#issuecomment-361215074

因为将答案嵌入 link 让我感到不舒服,这里是答案(归功于 Github 上的 xqwzts)。

使用您可以从任何地方访问的 GlobalKey 进行导航:

创建密钥:

final GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();

将其传递给您的应用程序:

new MaterialApp(
      title: 'MyApp',
      onGenerateRoute: generateRoute,
      navigatorKey: navigatorKey,
    );

推送路线:

navigatorKey.currentState.pushNamed('/someRoute');

这个问题的一个优雅的解决方案是使用GlobalKey。这会让您找到当前的 BuildContext 并使用它做一些事情。

您制作了一个名为 eg. global.dart 看起来像这样:

import 'package:flutter/material.dart';

class GlobalVariable {
  static final GlobalKey<NavigatorState> navState = GlobalKey<NavigatorState>();
}

您在 main()MaterialApp() 中像这样使用它:

import 'global.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'fcm.dart';  // My Firebase Cloud Messaging code
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'screens/welcome_screen.dart';


void main() {
  print('Running main()');
  WidgetsFlutterBinding.ensureInitialized();
  Firebase.initializeApp();
  initializeFcm('', GlobalVariable.navState); // Sending the global key when initializing Firebase Cloud Messaging
  FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);

  runApp(MyApp());
}


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: WelcomeScreen(),
      navigatorKey: GlobalVariable.navState,  // Putting the global key in the MaterialApp
    );
  }
}

然后,在我命名为 fcm.dart 的处理 Firebase 云消息传递的文件中,您将能够使用 GlobalKey 找到当前的 context 和使用它,例如像这样:

import 'package:blackbox/global.dart';
import 'online_screens/game_hub_screen.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';

void initializeFcm(String token, GlobalKey myGlobalKey) async {
  print('Initializing Firebase Cloud Messaging...');
  await Firebase.initializeApp();

  FirebaseMessaging.onMessageOpenedApp.listen((remoteMsg) {
    // Using the currentContext found with GlobalKey:
    Navigator.push(GlobalVariable.navState.currentContext, MaterialPageRoute(builder: (context) {
      return GameHubScreen();
    }));
  });
}