Flutter field has not been initialized - flutter

i have a bool that i set to true if the account datas is right but my bool is set to late and it doesnt works
My Model:
bool _result = false;
Future login(String username, String password) async {
var url = "http://192.168.178.75/flutterconn/login.php";
var response = await http.post(Uri.parse(url), body: {
"username": username,
"password": password,
});
var data = await json.decode(response.body);
if (data == "success") {
setResult(true);
Fluttertoast.showToast(msg: "Erfolgreich Eingeloggt",toastLength: Toast.LENGTH_SHORT,gravity: ToastGravity.CENTER,fontSize: 16.0);
}else {
Fluttertoast.showToast(msg: "Nicht Eingeloggt",toastLength: Toast.LENGTH_SHORT,gravity: ToastGravity.CENTER,fontSize: 16.0);
}
//print(_result);
notifyListeners();
}
Future setResult(bool rs) async{
_result = await rs;
notifyListeners();
}
bool getResult(){
return _result;
}
My onPressed Method:
context.read<LoginModel>().login(
usernameController.text, passwordController.text);
print(context.read<LoginModel>().getResult());
if (context.read<LoginModel>().getResult()) {
context.read<FoodSelectionModel>().loadGalleryLinks();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FoodSelectionScreen()),
);
}
My Error:
The following LateError was thrown while handling a gesture:
LateInitializationError: Field '_result#21188420' has not been initialized.
The Bool is turned to late to true how can i set it faster.

i tried with putting async on my onPressed method and await it works thank you guys.
onPressed: () async {
await context.read<LoginModel>().login(
usernameController.text, passwordController.text);
print(context.read<LoginModel>().getResult());
if (context.read<LoginModel>().getResult()) {
context.read<FoodSelectionModel>().loadGalleryLinks();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FoodSelectionScreen()),
);
}

Related

After get() of DocumentSnapshot, program is not executing next line in Flutter

Function1 and Function2 are not executed completely.
//Function1
Future<void> getUserDetails() async {
DocumentSnapshot documentSnapshot = await FirebaseFirestore.instance
.collection('users')
.doc('aLhON9H3H1ZpZvUB4ISUrK45Hk93')
.get();
if (documentSnapshot.exists) {
globalImagePath = documentSnapshot['imageURL'];
}
}
//Function2 (fetch data from subcollection of "users" collection
Future<void> fetchPunchinDetails() async {
try {
var result = await _users
.doc(user!.uid)
.collection('attendance')
.where('outTime', isEqualTo: null)
.get();
String dayStart = result.docs[0]['inTime'];
if (dayStart.isNotEmpty) {
dayStarted = true;
}
} catch (e) {
print(e.toString());
}
}
// Calling above two methods
_fetchAndGotoScreens() {
if (loginSuccess = true) {
getUserDetails(); //--------calling Function1
fetchPunchinDetails(); //----------calling Function2
//Go to attendance page-----------
Navigator.of(context)
.push(
MaterialPageRoute(
builder: (context) =>
Attendance(imagePath: imagePath, dayStartTime: dayStartTime),
),
)
.catchError((e) {
print(e);
});
} else {
// go to home page------------
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => MyHome()))
.catchError((e) {
print(e);
});
}
}
When I step through, in getUserDetails() itself, it returns to the calling method just after executing .get(). It is not even checking if (documentSnapshot.exists) condition. The same happens with fetchPunchinDetails() function. Please help..
fetchPunchinDetails and getUserDetails are future method, try using await before theses to complete.
_fetchAndGotoScreens() async{
if (loginSuccess = true) {
await getUserDetails();
await fetchPunchinDetails();

User gets internaly loged in, but UI does not change

So I have a problem with my app's login. When a user enters correct login data, he gets recognized on the firebase console, debug console also shows the user now exists, but the screen (which is controlled by StreamBuilder) does not change.
home: StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, AsyncSnapshot<User?> userSnapshot) {
if (userSnapshot.connectionState ==
ConnectionState.waiting) {
return LoadingSpinner();
}
if (userSnapshot.hasData) {
return MainScreen();
}
return AuthScreen();
}),
//.............
void authUser(String email, String password, bool isLogin,
String username) async {
setState(() {
isLoading = true;
});
UserCredential userCreadencial;
FocusScope.of(context).unfocus();
if (isLogin == false) {
userCreadencial = await firebaseAuth.createUserWithEmailAndPassword(
email: email,
password: password,
);
} else {
userCreadencial = await firebaseAuth.signInWithEmailAndPassword(
email: email,
password: password,
);
}
FirebaseFirestore.instance
.collection('users_info')
.orderBy(userCreadencial.user!.uid, descending: true);
await FirebaseFirestore.instance
.collection('users_info')
.doc(userCreadencial.user!.uid)
.set({
'email': userCreadencial.user!.email,
'username': username,
});
setState(() {
isLoading = false;
});
Debug console log:
W/System (14293): Ignoring header X-Firebase-Locale because its value
was null. 2 I/System.out(14293): (HTTPLog)-Static: isSBSettingEnabled
false D/FirebaseAuth(14293): Notifying id token listeners about user (
55epaBG5sGYJ7YWq1QZosJqrajT2 ).
I faced a simillar problem recently. I have found a workaround for this problem. You can use "whenComplete" function & a condition if the current user uid is not empty to navigate to the route after the signIn or login is successful. This is how your code might look like:
void authUser(String email, String password, bool isLogin,
String username) async {
setState(() {
isLoading = true;
});
UserCredential userCreadencial;
FocusScope.of(context).unfocus();
//to get current uid
String get currentUserUid => FirebaseAuth.instance.currentUser?.uid ?? '';
if (isLogin == false) {
//add whenComplete & check if the current uid is not empty.
userCreadencial = await firebaseAuth.createUserWithEmailAndPassword(
email: email,
password: password,
).whenComplete(
() => currentUserUid.isNotEmpty
? Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => MainScreen(),
),
(route) => false,
):null,
);;
} else {
//add whenComplete.
userCreadencial = await firebaseAuth.signInWithEmailAndPassword(
email: email,
password: password,
).whenComplete(
() => currentUserUid.isNotEmpty
? Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => MainScreen(),
),
(route) => false,
): null,
);;
}
FirebaseFirestore.instance
.collection('users_info')
.orderBy(userCreadencial.user!.uid, descending: true);
await FirebaseFirestore.instance
.collection('users_info')
.doc(userCreadencial.user!.uid)
.set({
'email': userCreadencial.user!.email,
'username': username,
});
setState(() {
isLoading = false;
});
you should also wrap your signIn and createUser function with try catch blocks

How to access future content

I have this function that is working inside a future builder:
Future<Data> fetchData(String barCode, String url) async {
final response = await http.get(Uri.parse(url + barCode));
Map<String, dynamic> novoJson = json.decode(utf8.decode(response.bodyBytes));
novoJson.forEach((key, value) {
if (value == null) {
novoJson.update(key, (value) => "Não encontrado");
}
});
if (response.statusCode == 200) {
return Data.fromJson(novoJson);
} else {
throw Exception('Failed to load album');
}
}
class Data {
final Map<String, dynamic> response;
Data({required this.response});
factory Data.fromJson(Map<String, dynamic> json) {
return Data(response: json);
}
}
Now i'm trying to access the json it returns inside a ElevatedButton, like this:
onPressed: () {
if (_formKey.currentState!.validate()) {
var futureData = fetchData(myController.text, args.url);
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(title: animacaoRespostaApi());
});
futureData.whenComplete(() {
Navigator.of(context).pop();
print(futureData);
return Navigator.pushNamed(context, args.rota, arguments: ParametrosRetornoConsulta(myController.text, args.url));
});
}
}
But when print it I get an instance of Future instead of the object, and I can't access it's content with futureData['id'] for example.
How can I make futureData stop being an Future and become a iterable object ?
Future<Data> fetchData is Future, you need to use await for data.
onPressed: () async {
if (_formKey.currentState!.validate()) {
var futureData = await fetchData(myController.text, args.url);

The argument type 'JsObject' can't be assigned to the parameter type 'BuildContext'

Heres when the error acquired, I wanted to change screen if the process is success and stayed if the process failed
Status() {
String rawJson =
LG();
Map<String, dynamic> map = jsonDecode(rawJson);
String status = map["STATUS"];
if (status == "Success") {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (_) => SPAL()),
(Route<dynamic> route) => false,
);
} else {
print("Failed");
}
}
here's where the it is executed
ButtonWidget(
text: 'Submit',
onClicked: () async {
if (_emailing.currentState.validate() &&
_passwd.currentState.validate()) {
Status();
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('email', emailController.text);
}
},
),
Don't return Navigator.pushAndRemoveUntil() and add the build context as param: Status(context)

NoSuchMethodError: Class 'FlutterError' has no instance getter 'code'. Receiver: Instance of 'FlutterError' Tried calling: code)

I've been trying a sample Flutter application code from GitHub to simply login and register the user on Firebase. Every time I login or register after clean building the application, it takes me to the main page but throws this exception Exception has occurred. NoSuchMethodError (NoSuchMethodError: Class 'FlutterError' has no instance getter 'code'. Receiver: Instance of 'FlutterError' Tried calling: code)
I've no idea what 'FlutterError' is referring to because I don't see any such class. and there are two occurrences of code in the file named 'login-register.dart'. I'm attaching the code below:
(Note: it runs okay after I hot reload the app and the user is already logged in, only throws exception the first time)
void _validateLoginInput() async {
final FormState form = _formKey.currentState;
if (_formKey.currentState.validate()) {
form.save();
_sheetController.setState(() {
_loading = true;
});
try {
final FirebaseUser user = (await FirebaseAuth.instance
.signInWithEmailAndPassword(email: _email, password: _password)).user;
// final uid = user.uid;
Navigator.of(context).pushReplacementNamed('/home');
} catch (error) {
switch (error.code) {
case "ERROR_USER_NOT_FOUND":
{
_sheetController.setState(() {
errorMsg =
"There is no user with such entries. Please try again.";
_loading = false;
});
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Container(
child: Text(errorMsg),
),
);
});
}
break;
case "ERROR_WRONG_PASSWORD":
{
_sheetController.setState(() {
errorMsg = "Password doesn\'t match your email.";
_loading = false;
});
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Container(
child: Text(errorMsg),
),
);
});
}
break;
default:
{
_sheetController.setState(() {
errorMsg = "";
});
}
}
}
} else {
setState(() {
_autoValidate = true;
});
}
}
void _validateRegisterInput() async {
final FormState form = _formKey.currentState;
if (_formKey.currentState.validate()) {
form.save();
_sheetController.setState(() {
_loading = true;
});
try {
final FirebaseUser user = (await FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: _email, password: _password)).user;
UserUpdateInfo userUpdateInfo = new UserUpdateInfo();
userUpdateInfo.displayName = _displayName;
user.updateProfile(userUpdateInfo).then((onValue) {
Navigator.of(context).pushReplacementNamed('/home');
Firestore.instance.collection('users').document().setData(
{'email': _email, 'displayName': _displayName}).then((onValue) {
_sheetController.setState(() {
_loading = false;
});
});
});
} catch (error) {
switch (error.code) {
case "ERROR_EMAIL_ALREADY_IN_USE":
{
_sheetController.setState(() {
errorMsg = "This email is already in use.";
_loading = false;
});
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Container(
child: Text(errorMsg),
),
);
});
}
break;
case "ERROR_WEAK_PASSWORD":
{
_sheetController.setState(() {
errorMsg = "The password must be 6 characters long or more.";
_loading = false;
});
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Container(
child: Text(errorMsg),
),
);
});
}
break;
default:
{
_sheetController.setState(() {
errorMsg = "";
});
}
}
}
} else {
setState(() {
_autoValidate = true;
});
}
}
The exception you're catching doesn't have a code property. That only exists with the firebase exception implementation, not the general exception class.
If you expect a certain type of error, you should explicitly catch that error and handle it properly and have a separate catch block for all other errors.
This can be done with an on ... catch block:
try {
final FirebaseUser user = (await FirebaseAuth.instance
.signInWithEmailAndPassword(email: _email, password: _password)).user;
// final uid = user.uid;
Navigator.of(context).pushReplacementNamed('/home');
} on FirebaseAuthException catch (error) {
...
} catch(e) {
...
}
The methods you're calling in the code you shared will throw FirebaseAuthExceptions as shown in the code above.
You are getting an error that is not a FirebaseError but a FlutterError. This means, it does not implement a code field.
You can simply put
if(!(error is FirebaseError)){
print(error.message); // this is the actual error that you are getting
}
right below catch(error) { (in both files) to handle this.
However, it seems like you get another Flutter Error that you might want to handle. It should be printed to the console now.