大家好,这是我一直在思考的问题。我也看到了一些回答,但它们并没有解决我的问题,我找到的一些类似的问题如下:Flutter showDialog with navigator key rather than passing context 或 Navigator operation requested with a context that does not include a Navigator
我想要实现的是从同一段代码中在应用的任何地方(因此在应用的任何页面)显示弹出对话框(因此都集中在一起)。问题在于,从那段代码中我没有访问BuildContext的权限,这是因为我基于不来自用户操作(例如按钮点击)的事件显示这些弹出对话框,而是可能是Firestore监听器或深入我的代码中发生的错误(因此我可以向用户显示错误消息),由于我深入了代码,通常我无法访问BuildContext。
在类似的问题中,我找到了一些看起来像解决方案的东西。这些解决方案使用一个全局键值(GlobalKey)来获取导航器,以便可以从应用程序的任何位置访问它,有一些不同的选项可以在应用程序的任何位置访问它,在我的情况下,我选择使用单例(我的“Repository”),在其中存储这个全局键值。然后当事件触发时,我使用全局键值来获取上下文并显示对话框,但它会抛出此错误:
Navigator operation requested with a context that does not include a Navigator.
The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.
@Hemanth Raj提到您的根Widget需要是MaterialApp,我的根已经是MaterialApp了。
以下是我所拥有的应用程序结构的近似表示:
void main() async {
// Here I create the navigatorKey
GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
// I then init my Singleton with the navigatorKey
await repository.init(navigatorKey: navigatorKey);
// Then I pass the navigatorKey down to my App
runApp(MyApp(debugMode: debugMode, navigatorKey: navigatorKey));
}
class MyApp extends StatefulWidget {
final navigatorKey;
const MyApp({Key key, this.navigatorKey})
: super(key: key);
@override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> with WidgetsBindingObserver {
@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: widget.navigatorKey,
title: 'My app',
home: SplashPage(),
theme: _buildMyTheme(),
);
}
}
那么在我的代码库中,我有一个监听器用于Firestore事件。这些事件可以随时在我进入主屏幕后触发。思路是无论我在应用程序的哪个位置,如果事件被触发,则应该弹出弹出窗口。
class Repository {
GlobalKey<NavigatorState> get navigatorKey => _navigatorKey;
GlobalKey<NavigatorState> _navigatorKey;
void init({GlobalKey<NavigatorState> navigatorKey}) {
_navigatorKey = navigatorKey;
}
void _listenToEvents() {
streamWithEvents.listen((event) {
showDialog(
context: navigatorKey.currentContext,
builder: (_) => CustomMessageDialog(message: event.message),
);
});
}
}