After get() of DocumentSnapshot, program is not executing next line in Flutter - 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();

Related

Flutter - Null check operator used on a null value

I am trying to retrieve user data using a DocumentSnapshot. However I am getting a casterror because the instance that I created is pointing to null. So I tried calling the method getUserProfileData in the initState method to see if it could assign a value to my DocumentSnapshot instance but I still get that error. Please may anyone kindly help.
//DocumentSnapshot instance that is null
DocumentSnapshot? userDocument;
getUserProfileData() {
FirebaseFirestore.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid)
.snapshots()
.listen((event) {
userDocument = event;
});
}
#override
void initState() {
getUserProfileData();
//This is where the castError occurs because userDocument is null
nameController.text = userDocument!.get('name');
userNameController.text = userDocument!.get('username');
try {
descriptionController.text = userDocument!.get('description');
} catch (e) {
descriptionController.text = '';
}
try {
followers = userDocument!.get('followers').length;
} catch (e) {
followers = 0;
}
try {
following = userDocument!.get('following').length;
} catch (e) {
following = 0;
}
}
It would be better to use StreamBuilder for firstore-snapshot.
late final stream = FirebaseFirestore.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid)
.snapshots();
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: stream,
builder: (context, snapshot) {....},
);
}
Also error can be bypass like
getUserProfileData() {
FirebaseFirestore.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid)
.snapshots()
.listen((event) {
userDocument = event;
/// all those stuff here
nameController.text = userDocument!.get('name');
userNameController.text = userDocument!.get('username');
..........
Try use async/await for getUserProfileData() function
getUserProfileData() async {
await FirebaseFirestore.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid)
.snapshots()
.listen((event) {
userDocument = event;
});
}
#override
void initState() {
getUserProfileData();
// Replace with default value case userDocument is null
nameController.text = userDocument!.get('name') ?? "";
userNameController.text = userDocument!.get('username') ?? "";
try {
descriptionController.text = userDocument!.get('description') ?? "";
} catch (e) {
descriptionController.text = '';
}
try {
followers = userDocument!.get('followers').length ?? 0;
} catch (e) {
followers = 0;
}
try {
following = userDocument!.get('following').length ?? 0;
} catch (e) {
following = 0;
}
}
Async determines that a method will be asynchronous, that is, it will not return something immediately, so the application can continue executing other tasks while processing is not finished.
await serves to determine that the application must wait for a response from a function before continuing execution. This is very important because there are cases where a function depends on the return of another.
a ?? b means that if the value of a is null, the value b will be assigned

How to read List of Instance of '_JsonQuerySnapshot' in Flutter

I am trying to read the data from a list that has the data of Instance of '_JsonQuerySnapshot'.
In the below code I am trying to get the data from DB
getData() async {
var db = FirebaseFirestore.instance;
var categoryList = [];
db.collection('categories')
.doc(value)
.get()
.then((DocumentSnapshot doc) {
var listSubCol = doc["categoryCollection"];
listSubCol.forEach((id) {
db.collection('categories')
.doc(value)
.collection(id)
.get()
.then((snapshot) {
categoryList.add(snapshot);
return categoryList;
});
});
});
}
Below is the code where I am printing the values.
FutureBuilder(
future: getData(),
builder: (BuildContext context, snapshot){
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.connectionState == ConnectionState.done) {
print('Data: ${snapshot.data}');
return Text("Text");
}
return Text("Text Outside");
}
)
I got a null value.
Can anyone please help me with how to get the data?
The getData is a Future<void>, so when the FutureBuilder is completed the snapshot.data is always null.
Change getData to return a List of whatever you are getting.
Future<List<Categories>> getData() async {
var db = FirebaseFirestore.instance;
final List<Categories> categoryList = [];
await db.collection('categories')
.doc(value)
.get()
.then((DocumentSnapshot doc) {
var listSubCol = doc["categoryCollection"];
listSubCol.forEach((id) {
db.collection('categories')
.doc(value)
.collection(id)
.get()
.then((snapshot) {
categoryList.add(snapshot);
return categoryList;
});
});
});
return categoryList;
}
getData() async {
var db = FirebaseFirestore.instance;
await db.collection('categories').doc(value).get().then((DocumentSnapshot doc) {
var listSubCol = doc["categoryCollection"];
listSubCol.forEach((id) {
db.collection('categories').doc(value).collection(id).get().then((snapshot) {
snapshot.docs.forEach((element) {
categoryList.add(element.data());
});
});
return categoryList;
});
});
return categoryList;
}
using the above method i got the data from Firestore.

Flutter field has not been initialized

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()),
);
}

flutter I want to get List<int> values ​as ints one by one

I want to get List values ​​as ints one by one.
where movieId requires an int value.
help me please
thank you
Future<MovieDetailModel> getMovieDetail(int? movieId) async {
try {
http.Response res = await http
.get(Uri.parse('$mainUrl/movie/$**movieId**?$apiKey&language=ko-KR'))
.timeout(Duration(seconds: 8),
onTimeout: () async => new http.Response('{}', 404));
if (res.statusCode == 404) {
return MovieDetailModel.fromJson({});
}
Map<String, dynamic> result = jsonDecode(res.body);
MovieDetailModel movies = MovieDetailModel.fromJson(result);
return movies;
} catch (e) {
print('MovieDetail $e');
}
return MovieDetailModel.fromJson({});
}
where user.userMovieId value is List .
Widget userMovie(UserModel user) {
return FutureBuilder(
future: this._movieDetailProvider.movies(**user.userMovieId!**),
builder:
(BuildContext context, AsyncSnapshot<MovieDetailModel> snapshot) {
if (snapshot.hasData) {}
Provider.
Future<MovieDetailModel> movies(int movieId) async {
MovieDetailModel movieList = await _movieRepo.getMovieDetail(movieId);
notifyListeners();
return movieList;
}

Flutter Futures: Waiting for listener to complete at least once

I am trying to implement a future return on a function that contains a listener. I want to complete this future when the listener has returned data at least once. I am not using async/await because the listen function is not a future. Hence, my option is the following:
static Future listenForConsumption() async {
Completer completer = Completer();
try {
kConsumptionCollection
.where("userId", isEqualTo: User.current.id)
.orderBy("consumptionDate", descending: true)
.snapshots()
.listen(
(data) {
consumptionList = data.documents
.map((doc) => ConsumptionUnit.data(doc.documentID, doc.data))
.toList();
streamController.add(consumptionList);
completer.complete();
},
);
} catch (err) {
completer.complete();
throw (err);
}
return completer.future;
}
By using a Completer I am trying to wait until the listener completes. However, the function that calls this one seems not to be awaiting for the future to complete:
void _checkForCurrentUser() async {
try {
await UserManager.fetchCurrentUser(); //Function waits for this
await Future.wait([
ConsumptionManager.listenForConsumption(),
BottleManager.listenForBottles(),
]); //Function does not wait for this
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Home()),
);
} catch (err) {
log("$err");
}
//...Rest of function
Any ideas of what can be missing?
Use something like this:
static void listenForConsumption(
{ #required Function onComplete,
#required Function onError,
}) async {
try {
kConsumptionCollection
.where("userId", isEqualTo: User.current.id)
.orderBy("consumptionDate", descending: true)
.snapshots()
.listen(
(data) {
consumptionList = data.documents
.map((doc) => ConsumptionUnit.data(doc.documentID, doc.data))
.toList();
onComplete(consumptionList);
},
);
} catch (err) {
onError(err);
}
}