Bloc: Ideal place for the root Bloclistener , to prevent pushNamedAndRemoveUntil from removing it from the widget tree

Created on 18 Oct 2020  路  4Comments  路  Source: felangel/bloc

This is more of design question than an issue but have spent quite a bit of time, any ideas how to resolve this will help. The functionality I am trying to get is after a user signs in, one should not be able to go back to the previous screen( the Signin screen). I am using pushNamedAndRemoveUntil() to reset the navigation but it also remove the widget that has the authBloc listener from the tree. So any further changes in the authentication state does not work.

Here is a sample project with the problem

https://github.com/mzafer/MyFlutterBloc

In main.dart, I create the authbloc and initialize it with the AppStarted event.

void main() {

  runApp(
    MultiBlocProvider(
      providers: [

        BlocProvider<AuthBloc>(
          create: (context) =>
            AuthBloc()
              ..add(AuthEvent_AppStarted())
        ),
      ],
      child: MyApp())
  );

}

The Start.dart is the first screen and has the BlocListener with the routing logic.


 @override
  Widget build(BuildContext context) {
     return BlocListener<AuthBloc, AuthState>(
        listener: ( context, state) {
          if (state is AuthState_Unauthenticated) {
            print('Route to Sign In');
            //Navigator.of(context).pushNamedAndRemoveUntil('/signIn', (route) => false);
            Navigator.of(context).pushNamed('/signIn');
          } else if (state is AuthState_Authenticated) {

            print('Route to Home');
            //Navigator.of(context).pushNamedAndRemoveUntil('/home', (route) => false);
            Navigator.of(context).pushNamed('/home');
          } 
        },
        child:Splash()
      );
  }

Using pushNamed here for routing allows any future AuthState changes to be listened and trigger appropriate actions but it also lets one to click on the back button and goto the previous screen. But using pushNamedAndRemoveUntil here fixes the back button issue but break the listener.

question

Most helpful comment

Thanks @felangel , did that and am good for now.

All 4 comments

Hi @mzafer 馃憤
Thanks for opening an issue!

I've opened a pull request with suggestions for how to simplify the navigation and achieve the desired outcome. Hope that helps!

Closing for now but feel free to comment with additional questions and I'm happy to continue the conversation 馃憤

Hi @felangel ,

Thanks for your response. The changes you recommended is where I started based on your various examples. But overtime my app has grown big and complex, so had to make some changes, 1) Moved all routing logic to it own service class, 2) Introduced fluro to manage routing. If I were to go back per your recommendation above it would bloat my Main.dart file. Any other alternative to accompalish this without moving the routing to the Main.dart ?

@mzafer you can extract the routing table to it's own file if you'd like

// routes.dart

final routes = {
  '/': (_) => Splash(),
  '/signIn': (_) => SignIn(),
  '/home': (_) => Home(),
};'

Then import routes in your app like:

Widget build(BuildContext context) {
  return MaterialApp(
    routes: routes,
    ...
  );
}

In terms of the routing logic I don't think it should grow because it should be scoped to just authentication related routing changes at the root. You can always decompose further into more widgets as needed though 馃憤

Thanks @felangel , did that and am good for now.

Was this page helpful?
0 / 5 - 0 ratings