How to store field value from firestore in Flutter? - flutter

For example, in the image below, I would like to store the value "hi" in a string in Flutter from Firestore. However, when I print the value, I keep getting Instance of 'Future<dynamic>'
Any idea how to do this?
Edit: One thing I am trying to do is basically get the data and see if its equal to a specific value. For example, if the field text is equal to "hello", then I would print "hi" to the screen
Code:
final firestoreInstance = FirebaseFirestore.instance;
final FirebaseAuth auth = FirebaseAuth.instance;
Future<String> getString(docID) async {
String? roleValue = '';
DocumentSnapshot docSnapshot = await firestoreInstance
.collection('messages')
.doc(docID)
.get();
roleValue = docSnapshot.data()!['text'];
return roleValue;
}

Seems like you are not awaiting the call as this is an async function.
You have to add await just before calling the getString function.
final result = await getString('abc);
print(result);
Now the result will no more Instance of 'Future<dynamic>'

Related

Type 'Future<QuerySnapshot<Map<String, dynamic>>>' is not a subtype of type 'DocumentSnapshot<Object?>' in type cast

static CollectionReference doses =
FirebaseFirestore.instance.collection('Doses');
void setDoseDetails(
TextEditingController endController,
TextEditingController startController,
TextEditingController doseController,
int noPills,
int doseRep) {
var dose =
doses.where('userID', isEqualTo: Auth().uID).get() as DocumentSnapshot;
Map<String, dynamic> userData = dose as Map<String, dynamic>;
endController.text = userData['endDate'];
startController.text = userData['startDate'];
noPills = userData['noPills'];
doseController.text = userData['doseVal'];
doseRep = userData["doseRep"];
}
I'm trying to retrieve data from Firebase using this code and it's not working.
If you see the return type of the get() method that you are trying to call in doses.where('userID', isEqualTo: Auth().uID).get() it is Future<QuerySnapshot<T>>. There are two problems in your approach:
You are not awaiting the result of doses.where('userID', isEqualTo: Auth().uID).get().
You are forcefully type-casting a QuerySnapshot into a DocumentSnapshot. If doses.where('userID', isEqualTo: Auth().uID).get() after awaiting, returns a QuerySnapshot, the variable holding that value should also be of the type QuerySnapshot.
Here is what you can do instead:
static CollectionReference doses =
FirebaseFirestore.instance.collection('Doses');
Future<void> setDoseDetails(
TextEditingController endController,
TextEditingController startController,
TextEditingController doseController,
int noPills,
int doseRep) async {
QuerySnapshot dose =
await doses.where('userID', isEqualTo: Auth().uID).get();
Map<String, dynamic> userData = dose as Map<String, dynamic>;
endController.text = userData['endDate'];
startController.text = userData['startDate'];
noPills = userData['noPills'];
doseController.text = userData['doseVal'];
doseRep = userData["doseRep"];
}
If you notice in the solution above,
I have changed the return type of setDoseDetails because it can't be just void and has to be Future<void> because you are dealing with futures.
I have put an await keyword in front of the doses.where('userID', isEqualTo: Auth().uID).get(). This will allow the response to return and be assigned to the variable dose.
To read more about futures I would suggest going through https://api.flutter.dev/flutter/dart-async/Future-class.html.
I hope that helps!
This might work for you:
var dose =
await doses.where('userID', isEqualTo: Auth().uID).get();
var userData = dose.docs.first.data();
endController.text = userData['endDate'];
startController.text = userData['startDate'];
noPills = userData['noPills'];
doseController.text = userData['doseVal'];
doseRep = userData["doseRep"];

_TypeError (type 'Null' is not a subtype of type 'FutureOr<String>')

I am trying to fetch profile image from firestore. But it is giving an error.
Here is the code of fuction which is use to get the image from database. Kindly help if you can
Future<String> getUserImage() async {
final uid = auth.currentUser?.uid;
final users = await firestore
.collection("app")
.doc("user")
.collection("driver")
.doc(uid)
.get();
return users.data()?['dp'];
}
Your getUserImage method cant return null, you can return default value return users.get('dp')?? "got null";
or accept nullable data
Future<String?> getUserImage() async {
final uid = auth.currentUser?.uid;
final users = await firestore
.collection("app")
.doc("user")
.collection("driver")
.doc(uid)
.get();
return users.get('dp');
}
Try the following code:
Future<String> getUserImage() async {
final String uid = auth.currentUser!.uid;
final DocumentSnapshot<Map<String, dynamic>> users = await firestore
.collection("app")
.doc("user")
.collection("driver")
.doc(uid)
.get();
return users.get('dp');
}

I am trying to save the notification title and body using shared preference but i am unable to

#I am trying to save the notification title and body locally and fetch the title and body inside my app to show all the sent notification in a listview but i am unable to
#this is the code i am running this code in my main.dart inside initstate and that detail.add is my list which i created manually but i am getting error saying 102:45: Error: This expression has type 'void' and can't be used.prefs.setString('notificationData', setData); when i try to setString this is the error i get
List<String?> detail = [];
FirebaseMessaging.onMessage.listen((message) async{
if(message.notification!=null){
// print(message.notification!.body);
// print(message.notification!.title);
final title = message.notification?.title;
final body = message.notification?.body;
SharedPreferences prefs = await SharedPreferences.getInstance();
final String notificationData = json.encode({"title":title,"body":body});
final setData = detail.add(notificationData);
prefs.setString('notificationData', setData);
print(notificationData);
print(setData);
}
The detail.add(notificationData) function returns nothing (void) and only adds to the existing array, so your setData variable is empty but you can use the original updated detail array like so:
FirebaseMessaging.onMessage.listen((message) async{
if(message.notification!=null){
// print(message.notification!.body);
// print(message.notification!.title);
final title = message.notification?.title;
final body = message.notification?.body;
SharedPreferences prefs = await SharedPreferences.getInstance();
final String notificationData = json.encode({"title":title,"body":body});
detail.add(notificationData);
prefs.setString('notificationData', detail.toString());
print(notificationData);
print(detail);
}
//...
});

returning a String when getting error: type 'Future<dynamic>' is not a subtype of type 'String'

I can't work out how to return a string from a function in Dart (a Flutter app).
I am using SharedPreferences to capture input from the user. I have two functions, one to save preferences:
save(key, value) async {
final prefs = await SharedPreferences.getInstance();
prefs.setString(key, value);
print('saved $value');
}
and one to read preferences:
read(key) async {
final prefs = await SharedPreferences.getInstance();
final value = prefs.getString(key) ?? 0;
print('$value');
}
This is working, but when I try to replace the print line with a return:
read(key) async {
final prefs = await SharedPreferences.getInstance();
final value = prefs.getString(key) ?? 0;
return('$value');
}
to return a string for the value, it throws an error:
type 'Future' is not a subtype of type 'String'
I have tried calling it many MANY different ways, but can't figure out what I assume is an incredibly basic problem. I noticed in some posts that this is a suggested solution, which works to print out the value, but I don't want to print it, i want it as a String variable:
read(mykey).then((value) => '$value');
I need to combine the value with other some other string values and make some minor manipulations (so printing it isn't helpful)
UPDATE
I have defined the function as #Stijn2210 suggested, but am still having problems getting the output i need.
Future<String> read(key) async {
final prefs = await SharedPreferences.getInstance();
final value = await prefs.getString(key) ?? '';
return value;
}
When I call this function from my app (this is a simplified snippet):
void onDragEnd(DraggableDetails details, User user) {
final minimumDrag = 100;
Future<String> myvalue;
if (details.offset.dx > minimumDrag) {
user.isSwipedOff = true;
save(user.imgUrl, 'Dog');
}
myvalue = read(user.imgUrl);
print(myvalue);
It's printing :
Instance of 'Future'
Whereas I want myvalue to be 'Dog'... Appreciate any insights!!
Really appreciate your answer #Stijn2202
Solution was to edit the method definition:
Future<void> onDragEnd(DraggableDetails details, User user) async
and then call the read function from the method with this:
final String myvalue = await read(user.imgUrl);
getString is a Future, which you can handle by using await or as you are doing, using then
However, in my opinion using await is your better option. This would look like this:
Future<String> getMyString() async {
final prefs = await SharedPreferences.getInstance();
final value = await prefs.getString(key) ?? '';
// Don't use 0, since it isnt an int what you want to return
return value;
}
EDIT:
based on your code snippet, this is how you should call your read method:
Future<void> onDragEnd(DraggableDetails details, User user) async {
final minimumDrag = 100;
if (details.offset.dx > minimumDrag) {
user.isSwipedOff = true;
save(user.imgUrl, 'Dog');
}
final String myvalue = await read(user.imgUrl);
print(myvalue);
}
Now I'm not sure if onDragEnd is actually allowed to be Future<void>, but let me know if it isn't
Just await for the value. It will return Dog and not instance of Future.
String someName=await myvalue;
As the value is Future, await keyword will wait until the task finishes and return the value

Flutter: how to get value from sharedpreferences? when i debug, the value is Instance of 'Future<String>'

i entered data using
Future<bool> saveSession() async{
final SharedPreferences pref = await SharedPreferences.getInstance();
return pref.setString('test', 'Some Data');
}
and get data using
Future<String> readSession() async{
final SharedPreferences pref = await SharedPreferences.getInstance();
return pref.getString('test');
}
when i try to debug it using
print(readSession()); // value is Instance of 'Future'
i dont know why ??
result is Instance of 'Future'
To get the string value you need to resolve the Future object first. There are basically two ways to achieve that:
1
print(await readSession());
2
readSession().then((v) => print(v));
You can read more about asynchronous operations in official docs - https://dart.dev/tutorials/language/futures