Please anyone suggest a way to secure "auto_route" routes using "flutter_bloc". In the above example My bloc state has been changed i.e. "authenticated" (Center text has been change to authenticated) But auth_guard never push route. Anyone help.

app_widget.dart


class AppWidget extends StatelessWidget {
  AppWidget({Key? key}) : super(key: key);

  final _appRouter = getIt<AppRouter>();

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      routerDelegate: _appRouter.delegate(),
      routeInformationParser: _appRouter.defaultRouteParser(),
      builder: (context, child) => BlocProvider(
        create: (context) => getIt<UserAuthenticationBloc>(),
        child: child,
      ),
    );
  }
}

user_authentication_page.dart

class UserAuthenticationPage extends StatelessWidget {
  const UserAuthenticationPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocConsumer<UserAuthenticationBloc, UserAuthenticationState>(
      listener: (context, state) {
        state.maybeMap(
          orElse: () => null,
          authenticated: (_) => context.router.push<bool>(const HomeRoute()),
        );
      },
      builder: (context, state) {
        return BlocBuilder<UserAuthenticationBloc, UserAuthenticationState>(
          builder: (context, state) {
            return Scaffold(
              body: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Center(
                    child: Text(
                      state.map(
                        authenticated: (_) => "authenticated",
                        unAuthenticated: (_) => "unAuthenticated",
                        loading: (_) => "loading",
                      ),
                    ),
                  ),
                  Align(
                    alignment: FractionalOffset.bottomCenter,
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Container(
                        width: double.maxFinite,
                        margin: const EdgeInsets.only(bottom: 24.0),
                        child: ElevatedButton(
                          onPressed: () => context
                              .read<UserAuthenticationBloc>()
                              .add(
                                  const UserAuthenticationEvent.requestLogin()),
                          child: const Text('Get Started'),
                          style: ButtonStyle(
                            shape: MaterialStateProperty.resolveWith(
                              (_) => const RoundedRectangleBorder(
                                borderRadius: BorderRadius.all(
                                  Radius.circular(8.0),
                                ),
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ),
                  if (state == const UserAuthenticationState.loading()) ...[
                    SizedBox(height: MediaQuery.of(context).size.height * 0.01),
                    const LinearProgressIndicator(value: null),
                  ],
                ],
              ),
            );
          },
        );
      },
    );
  }
}

user_authentication_bloc.dart

@injectable
class UserAuthenticationBloc
    extends Bloc<UserAuthenticationEvent, UserAuthenticationState> {
  UserAuthenticationBloc(this._userAuthenticationRepository)
      : super(
          const UserAuthenticationState.unAuthenticated(),
        ) {
    on<_RequestLogin>(_requestLogin);
  }

  final IUserAuthenticationRepository _userAuthenticationRepository;

  void _requestLogin(
      _RequestLogin event, Emitter<UserAuthenticationState> emit) async {
    emit(const UserAuthenticationState.loading());
    return emit(await _userAuthenticationRepository
        .redirectToLogin()
        .then(
          (value) => value.fold(
            (l) => const UserAuthenticationState.unAuthenticated(),
            (r) => const UserAuthenticationState.authenticated(),
          ),
        )
        .catchError((_) => const UserAuthenticationState.unAuthenticated()));
  }
}

router.dart

@MaterialAutoRouter(
  replaceInRouteName: 'Page,Route',
  routes: <AutoRoute>[
    AutoRoute(
      path: '/login',
      page: UserAuthenticationPage,
    ),
    AutoRoute(
      path: '/',
      page: HomePage,
      guards: [AuthGuard],
      children: [
        AutoRoute(
          path: 'dashboard',
          name: 'dashboardRouter',
          page: EmptyRouterPage,
          children: [
            AutoRoute(
              path: '',
              page: DashboardPage,
            ),
          ],
        ),
        AutoRoute(
          path: 'notifications',
          name: 'notificationRouter',
          page: EmptyRouterPage,
          children: [
            AutoRoute(
              path: '',
              page: NotificationPage,
            ),
          ],
        ),
        AutoRoute(
          path: 'settings',
          name: 'settingsRouter',
          page: EmptyRouterPage,
          children: [
            AutoRoute(
              path: '',
              page: SettingsPage,
            ),
          ],
        ),
      ],
    )
  ],
)
class $AppRouter {}

auth_guard.dart

@injectable
class AuthGuard extends AutoRouteGuard {
  final UserAuthenticationBloc userAuthenticationBloc;

  AuthGuard(this.userAuthenticationBloc);

  @override
  void onNavigation(NavigationResolver resolver, StackRouter router) {
    userAuthenticationBloc.state.map(
      loading: (_) => null,
      unAuthenticated: (_) => router.push(const UserAuthenticationRoute()),
      authenticated: (_) => resolver.next(),
    );
  }
}


Solution 1: Dagmawi Asfaw

The reason it doesn't navigate is because it is not getting the latest updated state. In order to get that you would have to listen to the state stream.

    @override
void onNavigation(NavigationResolver resolver, StackRouter router) {
  userAuthenticationBloc.stream.listen((state) {
    if (state is authenticated && !resolver.isResolved) {
      // TODO: ROUTE TO THE PAGE YOU WANT TO GO TO

     resolver.next(true);
    }
  },);
}