In order to Authenticate to Api, I created AuthProvider class to authenticate, after getting accessToken from the Api,I stored the token using sharedPreferences,I wanted to check if the user loggedIn or not, so I initialized sharedPreferences to return a boolean value if it contains the token... as shown in the code bellow:
class AuthProvider with ChangeNotifier{
bool _isLoading = false;
bool get isLoading => _isLoading;
User user = User();
late SharedPreferences prefs ;
String token = '';
Map<String, String> _mainHeaders = {
'Content-Type': 'application/json; charset=UTF-8',
};
void updateHeader(String token) {
_mainHeaders = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer $token',
};
}
Future<ResponseModel> login(String username, String password) async {
print("Getting token");
//print(authRepo.getUserToken().toString());
_isLoading = true;
notifyListeners();
http.Response response = await dologin(username, password);
// print('${response.body.}');
var answer = User.fromJson(jsonDecode(response.body));
print('the result is : ${answer.token}');
print('level 1: ${response.body.toString()}');
late ResponseModel responseModel;
print(response.statusCode);
if (response.statusCode == 200) {
//authRepo.saveUserToken((response.body["token"]).toString());
print("Backend token: ${response.body.toString()}");
responseModel = ResponseModel(true, answer.token!);
// SharedPreferences prefs = await SharedPreferences.getInstance();
// prefs.setString(ApiConstants.kEY_ACCESS_TOKEN, answer.token!);
storeToken(answer.token!);
} else {
responseModel = ResponseModel(false, response.reasonPhrase!);
}
_isLoading = false;
notifyListeners();
return responseModel;
}
bool userLoggedIn() =>
prefs.containsKey(ApiConstants.kEY_ACCESS_TOKEN) ? true : false;
// bool clearSharedData() => authRepo.clearSharedData();
void storeToken(String token) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString(ApiConstants.kEY_ACCESS_TOKEN, token);
print('the token is here : ${token}');
}
...
in main.dart I created a consumer to check if the user is loggedIn or not :
child: MaterialApp(
home: Consumer<AuthProvider>(
builder: ((context, auth, _){
return auth.userLoggedIn() ? const HomePage() : const loginScreen();
})
),
...
when I hit run I got the following error in my console:
The following LateError was thrown building Consumer(dirty, dependencies: [_InheritedProviderScope<AuthProvider?>]): LateInitializationError: Field 'prefs' has not been initialized. The relevant error-causing widget was Consumer. PS : I tried to initialize sharedPreferences : SharedPreferences? prefs; the error would be: Null check operator used on a null value. ...
CodePudding user response:
You're getting the error because you've marked your prefs
as late
but you haven't initialised it (as written in the error message). Just get rid of the line late SharedPreferences prefs;
at the top and ensure that you initialise it each time you need it within the method. I.e. call await SharedPreferences.getInstance();
each time.
CodePudding user response:
Future<bool> userLoggedIn() async{
prefs = await SharedPreferences.getInstance();
prefs.containsKey(ApiConstants.kEY_ACCESS_TOKEN) ? true : false;
}
Change userLoggedIn getter to this.
CodePudding user response:
You can call a function from init state and check the sharedprefrences in it like
late SharedPreferences prefs;
//initialize shared prefrences then access it
void initState() {
super.initState();
sharedData();
}
void sharedData() async {
prefs = await SharedPreferences.getInstance();
}
void storeToken(String token) async {
prefs = await SharedPreferences.getInstance();
prefs.setString(ApiConstants.kEY_ACCESS_TOKEN, token);
print('the token is here : ${token}');
}