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

荒凉一梦 提交于 2021-01-28 19:05:25

问题


I'm trying to create a BlocListener that has the ability to listen to all pages/routes throughout the app just like how you can access a Bloc or a Provider all throughout the app if they are defined at root-level like in the code below

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(),
          ),
        ),
      ),
    ),
  ),
);

As you can see, I have providers, blocs, and one listener. I have no problem accessing the blocs and providers in other pages. My problem is the auth listener. I lose access to the AuthListener once I move to a different page (by removing stack) , because it is inside the MaterialApp. However, in this instance, I need that specific listener (AuthListener) to be inside a MaterialApp, because it consists of code that uses page navigations (which doesn't work if the implementation is done outside/above the widget tree of a MaterialApp), and makes us of the MaterialApp context for showing dialogs.

My implementation of page routing which removes the stack, which is another cause of losing access to the AuthListener

Navigator.pushAndRemoveUntil(
        context,
        MaterialPageRoute(builder: (_) => route),
        (Route<dynamic> route) => false);

Why do I remove the route/page stack when moving to a different page?

  • I specifically use this after authentication. You don't really want a user to be able to press back button after logging in, andredirect the user back to the login page right? Usually back button should hide/close the app when they are logged in.

My AuthListener implementation

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,
    );
  }
}

Is there a different way around this?


回答1:


So I ended up defining a

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

and used it in my MaterialApp

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

So then, whenever I have to navigate in cases where the implementation is outside the MaterialApp (in my case via the AuthListener which is found at root-level, above the MaterialApp), I can navigate via

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

Which means I can finally have access to the MaterialApp navigator and context even with the listener outside the MaterialApp which allows me to do both navigation and showing of dialogs



来源:https://stackoverflow.com/questions/61295539/how-to-create-a-bloclistener-that-can-listen-to-all-pages-in-flutter-with-access

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!