'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 |
|---|
