如何创建一个可以通过访问 MaterialApp 上下文来监听所有页面的 BlocListener?

How to create a BlocListener that can listen to all pages in flutter with access to MaterialApp context?

我正在尝试创建一个 BlocListener,它能够在整个应用程序中收听所有 pages/routes,就像您可以访问 Bloc 或 [=15] 一样=] 如果它们像下面的代码一样在根级别定义,则贯穿整个应用程序

runApp(
  MultiProvider(
    providers: [
      ChangeNotifierProvider<IdentityTokenProvider>(
        create: (_) => IdentityTokenProvider(),
      ),
    ],
    child: MultiBlocProvider(
      providers: [
        BlocProvider<AuthBloc>(
          create: (_) => AuthBloc(),
        ),
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: AppConfig.DEBUGGABLE,
        theme: ThemeData(
            // fontFamily: CustomFontStyle.montserrat,
            ),
        home: AuthListener(
          child: Center(
            child: const MainApp(),
          ),
        ),
      ),
    ),
  ),
);

如您所见,我有提供者、集团和一个听众。我可以毫无问题地访问其他页面中的集团和提供商。我的问题是身份验证侦听器。一旦我移动到另一个页面(通过删除堆栈),我就无法访问 AuthListener,因为它在 MaterialApp 中。但是,在这种情况下,我需要将特定的侦听器 (AuthListener) 放在 MaterialApp 中,因为它包含使用页面导航的代码(如果实现完成 outside/above MaterialApp) 的小部件树,并使我们使用 MaterialApp 上下文来显示对话框。

我的页面路由实现删除了堆栈,这是无法访问 AuthListener

的另一个原因
Navigator.pushAndRemoveUntil(
        context,
        MaterialPageRoute(builder: (_) => route),
        (Route<dynamic> route) => false);

为什么我在移动到另一个页面时要删除 route/page 堆栈?

我的AuthListener实现

class AuthListener extends StatefulWidget {
  final Widget child;

  const AuthListener({Key key, @required this.child}) : super(key: key);

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

class _AuthListenerState extends State<AuthListener> {
  @override
  Widget build(BuildContext context) {
    return BlocListener<AuthBloc, AuthState>(
      listener: (context, state) {
        if (state is AuthAuthenticated) {
          PageRouterController.pushAndRemoveStack(context, const EcomPage());
        } else if (state is AuthUnauthenticated) {
          PageRouterController.pushAndRemoveStack(context, const LoginPage());
        }
      },
      child: widget.child,
    );
  }
}

是否有其他解决方法?

所以我最终定义了一个

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

并在我的 MaterialApp 中使用它

@override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: App.DEBUGGABLE,
      theme: ThemeData(
          // fontFamily: CustomFontStyle.montserrat,
          ),
      navigatorKey: App.navigatorKey,
      home: Center(
        child: const LoginPage(),
      ),
    );
  }

那么,每当我必须在 MaterialApp 之外进行导航时(在我的例子中是通过位于 MaterialApp 之上的根级别的 AuthListener),我可以通过

App.navigatorKey.currentState.pushAndRemoveUntil(
            MaterialPageRoute(builder: (_) => route),
            (Route<dynamic> route) => false);

这意味着我终于可以访问 MaterialApp 导航器和上下文,即使在 MaterialApp 之外的侦听器也允许我进行导航和显示对话框