I want to get the field data from FireStore - flutter

I want to get ['startTime] in this method.
But I can't get it.
I get the following error
The method 'data' isn't defined for the type 'Future'. Try correcting
the name to the name of an existing method, or defining a method named
'data'.
Future<String> getStudyTime()async {
final getStartTime =
await FirebaseFirestore.instance.collection('user').doc(uid()).get().data()['startTime'];
final DateTime now = DateTime.now();
final formatTime = DateFormat('hh:mm a').format(now);
var hh = now.hour;
var mm = now.minute;
var hhmm = "$hh:$mm";
studyTime = int.parse(hhmm);
return studyTime;
}
[FireStore Image]

Calling get() returns a Future, so you need to use await on get to get its value:
final doc = await FirebaseFirestore.instance.collection('user').doc(uid()).get();
final getStartTime = doc.data()['startTime'];
If you want to do this in a single line, use parenthesis to ensure the await works on get():
final getStartTime =
await (FirebaseFirestore.instance.collection('user').doc(uid()).get()).data()['startTime'];

Related

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);
}
//...
});

Unhandled Exception: type 'List<Set<Future<File>>>' is not a subtype of type 'List<File>' in type cast

I would compress a list of image file before uploading, but i have some doubts to convert type after using map a list of file, it return type List<Set<Future>>, not type List as I expect. How can I convert/cast to List of File in this situation, the compressImage function worked well with only one file. Thank you so much.
import 'package:image/image.dart' as Im;
import 'package:uuid/uuid.dart';
List<File> compressImageList(List<File> tempfileList) async {
List<Future<File>> compressedFileList =
tempfileList.map((file) => {compressImage(file)}).toList();
return compressedFileList ;
}
Future<File> compressImage(File tempFile) async {
String postId = Uuid().v4();
final tempDir = await getTemporaryDirectory();
final path = tempDir.path;
Im.Image? imageFile = Im.decodeImage(tempFile.readAsBytesSync());
final compressedImageFile = File('$path/img_$postId.jpg')
..writeAsBytesSync(Im.encodeJpg(imageFile!, quality: 85));
tempFile = compressedImageFile;
return tempFile;
}
i edit my function as below and it works , thank you.
Future<List<File>> compressImageList(List<File> tempfileList) async {
List<File> compressedFileList = [];
await Future.wait(tempfileList.map((file) async {
var compressImage2 = await compressImage(file);
compressedFileList.add(compressImage2);
}).toList());
return compressedFileList;
}
Not sure, haven't tested it, but try removing the {} on the 6th line (as shown above). These brackets signify that it is a type set, which is being returned by =>. If using => for a single statement you don't need to use brackets.
Do it like this;
List<File> compressImageList(List<File> tempfileList) {
List<File> compressedFiles = [];
tempfileList.forEach((file) async {
final compressedFile = await compressImage(file);
compressedFiles = [...compressedFiles, compressedFile];
});
return compressedFiles;
}

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 can use String data outside future method?

I have this future method to get a data from server and using it :
Future<String> get_week() async {
var weekUrl =
'https://xxx/api/controller/matchs/active_week.php';
var weekresponse = await http.get(weekUrl);
var weekdata = await jsonDecode(weekresponse.body);
var weekId = weekdata[0]['w_id'];
return weeId
}
How can i use the value of weekId outside this method?
You can use the await keyword to assign the returned value from the future to variable:
String id = await get_week();

Type 'List<dynamic>' is not a subtype of type 'List<SubCategoryData>'

I am trying to assigning the list to list of object, but it is showing the above exception.
List<SubCategoryData>categoryNames = new List<SubCategoryData>();
List<String>categorieslist = [];
bool isFirst=true;
Future<SubCategoryModel>fetchCategories(BuildContext context) async {
String url = "http://106.51.64.251:380/onnet_api/subcatListByCategory.php";
var body = new Map<String,String>();
body['publisherid']= 102.toString();
body['tag'] = "category";
body['subtag']= "list";
body['parentId'] = 10.toString();
http.Response res = await http.post(url,body: body);
final categoryjsondata = json.decode(res.body);
var map = Map<String,dynamic>.from(categoryjsondata);
var categoryResponse = SubCategoryModel.fromJson(map);
if(res.statusCode == 200){
print('category Response: $categoryResponse');
if(categoryResponse.status == 1){
//final categoryModel = json.decode(res.body);
categoryNames = categoryjsondata['data']as List;
print('category data: $categoryNames');
/* for(var model in categorieslist){
categoryNames.add(new SubCategoryData.fromJson(model));
}*/
/* SharedPreferences prefs = await SharedPreferences.getInstance();
print("cat List Size: $categories");
prefs.setStringList("categorylist", categories);*/
Navigator.push(context, MaterialPageRoute(builder: (context)=> ChewieDemo(imageData: images[0],
categoryData:categoryNames.toList())));
}
}
}
By seeing my code, for categoryNames I am trying to assigning the data to this then it is showing the exception.
Try to change your code to:
List<SubCategoryData> categoryNames = new ArrayList<>();
Hopefully this will solve your problem.
replace the following:
categoryNames = categoryjsondata['data']as List;
by
for(var model in categoryData){
categoryNames.add(new SubCategoryData.fromJson(model));
}
because the first returns a List the second returns a List
Your problem resides here:
categoryNames = categoryjsondata['data']as List;
categoryNames is already defined and initialized and its type is List<SubCategoryData>. In the line above you are trying to assign a List<dynamic> to it. That's a different type and that's the cause of the error. If you assign that to some other variable you can use it freely:
final categoryNamesList = categoryjsondata['data'] as List;
BTW then you don't have to call .toList() in the next lines, because this variable is already a list.
If explicity not defined the lists are of type dynamic, So explicitly state the value of the model. i.e
Convert
categoryNames = categoryjsondata['data']as List;
to
categoryNames = List<SubCategoryData>.from(categoryjsondata['data']);