Ad

Flutter Cubit With BlocListener: How Can I Navigate The User According To State?

I have a basic auth cubit, and in the state, it has just one variable.

@freezed
class AuthState with _$AuthState {
  const AuthState._();

  const factory AuthState({
    required bool isUserSignedIn,
  }) = _AuthState;

  factory AuthState.initial() => const AuthState(isUserSignedIn: false);
}

In the cubit part, I can easily check is user Logged in or not via FirebaseAuth.instance.authStateChanges().listen((User? user)) method in the debug console.

Now, the problem starts in the landing page section. There are some things that create problems.

First things first, you can see the landing page codes below. Here, I have initState for the initial (when App starts, it works first), and after that, I return BlocListener for the listen to the cubit's state. When I click the login button and also the log out button, it works properly (I can see it in the debug console, I can log out but the same screen continues to stay, after I reload the app, then I can see I have already exited).

In the BlocListener section, I tried to print some texts, but they do not work, I mean I can not see them in the debug console.

class LandingPage extends StatefulWidget {
  const LandingPage({Key? key}) : super(key: key);

  @override
  State<LandingPage> createState() => _LandingPageState();
}

class _LandingPageState extends State<LandingPage> {
  @override
  void initState() {
    WidgetsBinding.instance!.addPostFrameCallback((_) {
      final bool isUserSignedIn =
          context.read<AuthCubit>().state.isUserSignedIn;
      if (isUserSignedIn) {
        AutoRouter.of(context).replace(const HomeRoute());
      } else if (!isUserSignedIn) {
        AutoRouter.of(context).replace(const SignInRoute());
      }
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return BlocListener<AuthCubit, AuthState>(
      listenWhen: (p, c) => p.isUserSignedIn != c.isUserSignedIn,
      listener: (context, state) {
        final bool isUserSignedIn =
            context.read<AuthCubit>().state.isUserSignedIn;

        if (isUserSignedIn) {
          print("blocblocbloc1");
          AutoRouter.of(context).replace(const HomeRoute());
        } else {
          print("blocblocbloc2");
          AutoRouter.of(context).root.popUntilRoot();
        }
      },
      child: const Scaffold(
        body: Center(
          child: CircularProgressIndicator(color: Colors.white),
        ),
      ),
    );
  }
}

Apart from that, I use autoroute for the rotation (Since I do not want to see a direct widget, I want to navigate users according to their login state). Firstly I thought maybe AutoRouter does not work, but the print statement also does not work.

Here I also share my main.dart file.

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

  @override
  Widget build(BuildContext context) {
    final _appRouter = AppRouter();
    return BlocProvider(
      lazy: true,
      create: (context) => AuthCubit(),
      child: MaterialApp.router(
        routeInformationParser: _appRouter.defaultRouteParser(),
        routerDelegate: _appRouter.delegate(),
        debugShowCheckedModeBanner: false,
      ),
    );
  }
}

Lastly, my router page is here.

@MaterialAutoRouter(
  replaceInRouteName: 'Page,Route',
  routes: <AutoRoute>[
    AutoRoute(page: LandingPage, initial: true),
    AutoRoute(
      page: HomePage,
    ),
    AutoRoute(
      page: SignInPage,
    ),
  ],
)
class $AppRouter {}
Ad

Answer

solution: use flow_builder to navigate user according to state

Ad
source: stackoverflow.com
Ad