I would like to get the value of my variable,
i used provider to manage the state. the problem is that i cannot get the new value of the boolean variable. The problem is particular to this variable, the others i can get the values.
here is my code :
class AuthProvider extends ChangeNotifier {
bool _isAuthenticated = false;
late AuthUseCase authUseCase;
LoginResponse _userResponse = LoginResponse.empty();
UserAccountDto _userAccountDto = UserAccountDto.empty();
ForgotPasswordDto _forgotPasswordDto = ForgotPasswordDto();
ForgotPasswordDto get forgotPasswordDto => _forgotPasswordDto;
set forgotPasswordDto(ForgotPasswordDto value) {
_forgotPasswordDto = value;
}
UserAccountDto get userAccountDto => _userAccountDto;
set userAccountDto(UserAccountDto value) {
_userAccountDto = value;
}
bool get isAuthenticated => _isAuthenticated;
LoginResponse get userResponse => _userResponse;
set userResponse(LoginResponse value) {
_userResponse = value;
notifyListeners();
}
Future<String> login(String email, String password) async{
authUseCase = new AuthUseCase();
dynamic responseFromWs = await authUseCase.login(email,password);
return processToWsResponse<LoginResponse>(responseFromWs,LoginResponse,isForLogin: true);
}
Future<String> registerDriver(UserAccountDto userAccountDto) async {
authUseCase = new AuthUseCase();
dynamic responseFromWs = await authUseCase.registerDriver(userAccountDto);
return processToWsResponse<UserAccountDto>(responseFromWs,UserAccountDto);
}
Future<String> sendActivationCode(String email) async {
authUseCase = new AuthUseCase();
dynamic responseFromWs = await authUseCase.sendActivationCode(email);
return processToWsResponse<UserAccountDto>(responseFromWs,UserAccountDto);
}
Future<String> changePassword(ForgotPasswordDto data) async {
authUseCase = new AuthUseCase();
dynamic responseFromWs = await authUseCase.changePassword(data);
return processToWsResponse<UserAccountDto>(responseFromWs,UserAccountDto);
}
String processToWsResponse<T>( dynamic responseFromWs, dynamic T, {bool? isForLogin}){
String responseToShowToUser = "";
if(responseFromWs is! String) {
if(isForLogin != null) {
_isAuthenticated = true;
notifyListeners();
print("valeur de authenticated "+isAuthenticated.toString());
}
if(isForLogin != null) {
userResponse = LoginResponse.fromMap(responseFromWs);
}
return "";
}else{
responseToShowToUser = responseFromWs;
}
return responseToShowToUser;
}
void logout() {
_isAuthenticated = false;
notifyListeners();
}
}
then the code of the main :
var globalMessengerKey = GlobalKey<ScaffoldMessengerState>();
void main() {
WidgetsFlutterBinding.ensureInitialized();
Future.wait([
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]),
//PrefUtils().init()
]).then((value) {
runApp(MyApp());
});
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Sizer(
builder: (context, orientation, deviceType) {
return MultiProvider(
providers: [
ChangeNotifierProvider<AuthProvider>(create: (context) => AuthProvider())
],
builder : (context, child) =>
MaterialApp(
title: 'trennko',
debugShowCheckedModeBanner: false,
theme: theme,
localizationsDelegates: [
AppLocalizationDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate
],
supportedLocales: [Locale('en', '')],
home: Consumer<AuthProvider>(
builder: (context, auth, child)
{
return auth.isAuthenticated ? HomePage() : LoginPage() ;
})
));
},
);
}
}
when i loggedIn successfully, i go out of the application and come back, the page loaded is the loginPage.
Providers are basically fancy listeners. It essentially just allows one widget to react to a state change from another widget. But your data is still on regular variables on RAM, Providers do not persist any data to disk. A simple example use case of a Provider is a dark/light mode toggle. Whe the user change the toggle widgets all over the widget tree need to be notified of the change.
Provider can be useful for auth, to handle real time changes to Auth state while the app is running but you still need a different solution to persist data to disk. I recommend using Hive https://pub.dev/packages/hive.
You would open a box on the main func (you can also make it async and avoid using Future.wait):
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
//await PrefUtils().init()
await Hive.openBox('auth');
runApp(MyApp());
}
Then add a constructor to AuthProvider
and initialize _isAuthenticated
with the value from Hive. Also remember to always update Hive when change _isAuthenticated
.
class AuthProvider extends ChangeNotifier {
late bool _isAuthenticated;
final authBox = Hive.box("auth");
...
AuthProvider() {
_isAuthenticated = authBox.get('isAuth', defaultValue: false);
}
...
if(isForLogin != null) {
_isAuthenticated = true;
authBox.put('isAuth', true);
notifyListeners();
print("valeur de authenticated "+isAuthenticated.toString());
}
}