I have a big problem using state management with Providers and the navigator.
Things that we must know:
1) My RESTFUL API gives a token that expires on 12h.
2) My home: parameter is conditioned if the user is authenticated or nor.. if not, based in other parameters I must decide what screen must be the home.
3) If I'm on one screen and the token gets expired on ANY request that the app is doing to the API I:
- Call a function inside my
auth
provider that do logout procedures, (i clean the localStorage with the token). Thisauth
provider sets a property calledisAuth
tofalse
. - When
isAuth
is false, if you look themain.dart
file athome:
you will see that will show theLoginPage()
.
Everything here is good. The problem is when i must do a redirect using the Navigator.of...
.. If, for example, in case of error of token expired I do: Navigator.popUntil(context, ModalRoute.withName('/login'));
the app goes to the LoginPage()
without problem, but... when I try to use the login (using the login
function of auth
provider) it's stay on the login page! If I use in any place the Navigator
to go to any other place, it's appears to override the 'state management way' that I use to control which page shows as home
.
Can you help me please?
My main.dart
code:
// Providers
import 'package:provider/provider.dart';
import 'package:cadsanjuan_movil/providers/auth.dart';
// Pages
import './pages/login_page.dart';
import './pages/initial_loading_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
final storage = new FlutterSecureStorage();
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<Auth>(create: (context) => Auth()),
ChangeNotifierProvider<TurnActive>(create: (context) => TurnActive()),
ChangeNotifierProxyProvider<TurnActive, Checkup>(
create: (context) => Checkup(),
update: (_, turnActive, checkup) {
checkup.turnData = turnActive.turnData;
return checkup;
}),
ChangeNotifierProxyProvider<Auth, ErrorProvider>(
create: (context) => ErrorProvider(),
update: (_, auth, errorProvider) {
errorProvider.logoff = auth.logoff;
return errorProvider;
}),
],
child: Consumer3<Auth, TurnActive, Checkup>(
builder: (context, auth, turnActive, checkup, _) {
return MaterialApp(
title: 'CAD App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: auth.isAuth
? (turnActive.turnData != null &&
turnActive.turnData['turn']['checkUpStartId'] != null)
? CheckupPage() // Si el cotejo está en proceso
: InitialLoadingPage() // Si no hay cotejo iniciado
: FutureBuilder(
// Si estamos no hay autenticación en el estado, se chequea en el localStorage
future: auth.tryAutoLogin(),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState ==
ConnectionState.waiting
? LoadingData()
: LoginPage(),
),
routes: {
LoginPage.routeName: (context) => LoginPage(),
InitialLoadingPage.routeName: (context) => InitialLoadingPage(),
CheckupPage.routeName: (context) => CheckupPage(),
CheckupGroupsPage.routeName: (context) => CheckupGroupsPage(),
},
);
},
));
}
}