wafutech
wafutech

Reputation: 551

Flutter App Back button is closing the App instead of navigating to the previous screen in flutter Navigation 2.0 with bloc and cubit

I am working on a flutter App and managing state using bloc architecture and cubits for navigation. The App is a bit large and complicated. The issue I am having is when I tap the Android back button; it closes the App instead of poping to the previous screen. I understand I have to use Route delegates and other custom navigation setup but not sure if this could be the right solution or simply fit in my app architecture.

This is the structure of my App. There four different user groups. Each user group is redirected to own dashboard after login. All user groups are sharing the AppNavigator and AuthNavigator at entry point. But after login, a use can only access his dashboard and routes there under.

AppNavigator ---> Is user logged in? if true redirect to session navigator else redirect to auth navigator. The app navigator checks if the user is authenticated and if yes redirects to switchboard which will check the user type and then redirect to appropriate dashboard. Each user group navigation flow have a high level navigation cubit the handles the navigation. Here is part of my code:

//main.dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    String appTitle = 'App Title';
    AuthRepository authRepository = AuthRepository();
    SessionCubit sessionCubit = SessionCubit();

    return MultiBlocProvider(
        providers: [
          BlocProvider<AuthCubit>(
            create: (context) => AuthCubit(sessionCubit: sessionCubit),
          ),
          BlocProvider<UserGroup1Cubit>(
            create: (context) => UserGroup1Cubit(),
          ),
          BlocProvider<UserGroup2Cubit>(
            create: (context) => UserGroup2Cubit(),
          ),
          ...
        ],
        child: MaterialApp(
            title: appTitle,
            debugShowCheckedModeBanner: false,
            theme: lightThemeData(context),
            darkTheme: darkThemeData(context),
            home: MultiRepositoryProvider(
              providers: [
                RepositoryProvider<AuthRepository>(
                    create: (context) => AuthRepository()),
              ],
              child: BlocProvider(
                  create: (context) =>
                      SessionCubit(authRepo: context.read<AuthRepository>()),
                  child: AppNavigator()),
            )));

   



    //AppNavigator.dart
        //This navigator will redirect to authnavigator if the user is unauthenticated or SwitchBoard() of authenticated passing in user type from the state

 class AppNavigator extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<SessionCubit, SessionState>(builder: (context, state) {
   
      return Navigator(
          // key:navigatorKey,
          pages: [
            //show loading screen
            if (state is UnknownSessionState)
              MaterialPage(child: SplashScreen()),

            //show auth flow
            if (state is UnauthenticatedState)
              MaterialPage(
                  child: BlocProvider(
                create: (context) =>
                    AuthCubit(sessionCubit: context.read<SessionCubit>()),
                child: AuthNavigator(),
              )),

            //show session flow
            if (state is AuthenticatedState)
              MaterialPage(
                  child: BlocProvider(
                create: (context) => SessionCubit(authRepo: AuthRepository()),
                child: SwitchBoard(userType: state.user!.type),
             
              )),
          ],
          onPopPage: (route, result) {
            if (!route.didPop(result)) return false;
            return true;
          });
    });
  }
}

//switchboard.dart

class SwitchBoard extends StatelessWidget {
  final String? userType;
  SwitchBoard({Key? key, this.userType}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<SessionCubit, SessionState>(builder: (context, state) {
      return Navigator(
        pages: [
          if (userType == 'group1')
            MaterialPage(
                child: BlocProvider(
                    create: (context) => Group1Cubit(
                        sessionCubit: context.read<SessionCubit>()),
                    child: UserGroup1Navigator())),
          if (userType == 'group2') MaterialPage(child: UserGroup2Navigator()),
          ...
        ],
        onPopPage: (route, result) {
          return route.didPop(result);
        },
      );
    });
  }
}
 As indicatted in the code, each user group have its own navigator and navigation cubit
 //UserGroup1Navigator

 class UserGroup1Navigator extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<Group1Cubit, Group1State>(builder: (context, state) {
      return Navigator(
        pages: [
          //show show group dashboard
          if (state is Group1DashboardState)
            MaterialPage(
                key: const ValueKey('Group1Dashboard'),
                child: Group1Dashboard()),
          if (state is ProfileState)
            MaterialPage(
                key: const ValueKey('UserProfile'),
                child: UserProfile()),
                ...
          
        ],
        onPopPage: (route, result) => route.didPop(result),
      );
    });
  }
}

Each user group have its navigator trigered by navigation cubit methods and is working fine via the BlocProvider like so:

//Navigate to UserProfile from anywhere in the app
BlocProvider.of<Group1Cubit>(context).showGroup1UserProfile();

The only problem is that cannot navigate back by pressing the back button on Android device. This will close the App instead. Any work around on this will appreciate.

Upvotes: 6

Views: 2545

Answers (2)

Ndiaga GUEYE
Ndiaga GUEYE

Reputation: 391

Just remove android:enableOnBackInvokedCallback="true" in your Manifest file

Upvotes: 1

Vladlen Volkov
Vladlen Volkov

Reputation: 168

I'm pretty much new into dart and flutter, so if it isn't connected to the topic, please, don't judge strict.

I found this thread and it worked for me. Check it out.

In a nutshell, the only way to set it up is to use WillPopScope.

Upvotes: 1

Related Questions