'How to deal with Navigator (screens routing) when using Provider for state management

I am learning about providers and ChangeNotifier, I am using the following pattern on my pages:

                Wrapper widget (consumer to switch between pages on notifyListners())
                |         |
                |         |
             login     MyHome 
                          |
                       Deep widget 1 (logout here cannot take me to login page)
                          |
                       Deep widget 2 (logout here cannot take me to login page)

A wrapper widget to choose between login or home page:

class Wrapper extends StatelessWidget {
const Wrapper({Key? key}) : super(key: key);
static final String route = 'wrapper';

@override
Widget build(BuildContext context) {
  return Consumer<AuthState>(
    builder: (context, provider, child) {
      if (provider.isAuth) return MyHomePage();
      return Login();
    },
  );
}}   

Login Page:

class Login extends StatelessWidget {
const Login({Key? key}) : super(key: key);
static final String route = 'login';

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Container(),
        Text('Login : You are here!  -  Home'),
        Text('Deep widget 1'),
        Text('Deep widget 2'),
        TextButton(
          onPressed: () {
            Provider.of<AuthState>(context, listen: false).login();
          },
          child: Text('login'),
        ),
      ],
    ),
  );
}}

Home page:

class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
static final String route = 'login';

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Container(),
        Text('Login -  Home : You are here! '),
        Text('Deep widget 1'),
        Text('Deep widget 2'),
        TextButton(
          onPressed: () {
            Navigator.pushNamed(context, DeepWidget1.route);
          },
          child: Text('go deeper'),
        ),
        TextButton(
          onPressed: () {
            Provider.of<AuthState>(context, listen: false).logout();
          }, 
          child: Text('logout'),
        ),
      ],
    ),
  );
}}

Deep widget 1 by push navigation:

class DeepWidget1 extends StatelessWidget {
const DeepWidget1({Key? key}) : super(key: key);
static final String route = 'd1';

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Container(),
        Text('Login  -  Home'),
        Text('Deep widget 1 : you are here!'),
        Text('Deep widget 2'),
        TextButton(
          onPressed: () {
            Navigator.pushNamed(context, DeepWidget2.route);
          },
          child: Text('go even deeper'),
        ),
        TextButton(
          onPressed: () {
            Provider.of<AuthState>(context, listen: false).logout();
          },
          child: Text('logout'),
        ),
      ],
    ),
  );
}}

Deep widget 2 by push navigation:

class DeepWidget2 extends StatelessWidget {
const DeepWidget2({Key? key}) : super(key: key);
static final String route = 'd1';

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Container(),
        Text('Login  -  Home'),
        Text('Deep widget 1'),
        Text('Deep widget 2 : you are here!'),
        TextButton(
          onPressed: () {
            Provider.of<AuthState>(context, listen: false).logout();
          },
          child: Text('logout'),
        ),
      ],
    ),
  );
}}

Main:

void main() {
runApp(
  MultiProvider(
    providers: [
      ChangeNotifierProvider(create: (_) => AuthState()),
    ],
    child: MaterialApp(
        initialRoute: Wrapper.route,
        routes: {
          MyHomePage.route: (context) => MyHomePage(),
          Login.route: (context) => Login(),
          DeepWidget1.route: (context) => DeepWidget1(),
          DeepWidget2.route: (context) => DeepWidget2(),
        },
        home: Wrapper()),
  ),
);}

Finally the provider class:

class AuthState extends ChangeNotifier {
static bool authFlag = false;

bool get isAuth => authFlag;

void login() {
  authFlag = true;
  notifyListeners();
}

void logout() {
  authFlag = false;
  notifyListeners();
}
}

how to handle such a situation so that the login page will be displayed automatically when the user logs out from a deep widget.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source