do Something with specifed time & firebase - flutter

I just want to print "After Time" when my local time is greater than my Firebase data document, but it does nothing when my local time is greater only when I restart my application, it shows up print I want it right now displayed
ssaveTimeToFireStrone() async{
await FirebaseFirestore.instance.collection("TimeToChange").doc("Time").set({
"currentTime":atSixInEvening
});
}
Future getTheTime() async{
final DocumentSnapshot doc=await FirebaseFirestore.instance.collection("TimeToChange").doc("Time").get();
DateTime timeToTriggerEvent=doc["currentTime"].toDate();
// await Future.delayed(Duration(seconds: 5));
// print(timeToTriggerEvent);
if(await DateTime.now().isAfter(timeToTriggerEvent)){
print("after time");
return true;
}
}

Thats because the Future is only called once (probably when you start the app).
If you want to continously check if the time is after the trigger time then you have to put it in a loop. I would suggest a timer that checks once every second (so it doesn't cause any performance impact).
How to use the Timer: How to set an Interval in Flutter?

Related

Flutter - Waiting for an asynchronous function call return from multiple synchronous function calls

I have an async function which is called multiple times synchoronusly.
List response = await Future.wait([future, future])
Inside, it popups a form and waiting for it to be submitted or cancelled.
var val = await Navigator.push(
context,
MaterialPageRoute(builder : (context) => const TheForm())
);
The first served Future will popup the form first and waiting for the return. No problem with that. But I want the second Future to check first if the form is already popped up. If it is, it just waiting for it to conclude and receive the same returned value.
I'm aware that receiving same function return from two calls sounds crazy and impossible. I'm just looking for a way to hold the second Future call on and trigger to conclude it from somewhere else.
Kindly tell me what I was missing and I'll provide the required information.
I try to use ValueNotifier's. Unfortunately ValueNotifier.addListener() only accept a VoidCallback. As for now, this is my solution. Still looking for a better way to replace the loop.
Future future() async{
if(ison) await Future.doWhile(() async {
await Future.delayed(Duration(seconds: 1));
return ison;
});
else{
ison = true;
result = ... //Popup form
ison = false;
}
return await result;
}
It sounds like you want to coalesce multiple calls to an asynchronous operation. Make your asynchronous operation cache the Future it returns and make subsequent calls return that Future directly. For example:
Future<Result>? _pending;
Future<Result> foo() {
if (_pending != null) {
return _pending!;
}
Future<Result> doActualWork() async {
// Stuff goes here (such as showing a form).
}
return _pending = doActualWork();
}
Now, no matter how many times you do await foo();, doActualWork() will be executed at most once.
If you instead want to allow doActualWork() to be executed multiple times and just to coalesce concurrent calls, then make doActualWork set _pending = null; immediately before it returns.

not concurrent version of map in flutter streams

I am using Streams in Flutter. The problem is that stream.map() is concurrent which means that it doesn't wait one operation to be performed completely. For example:
_sendClientSubject.stream.map((value) async {
await Future.delayed(const Duration(hours: 1));
// do some operation
}).listen((value) {
// do nothing
});
Here, I want the next stream value to wait until I finish my operation. But the case is, instead of waiting for an hour, map is processing each stream value concurrently.
My question is, how can I perform the operation synchronously in Flutter.
Use asyncMap method from rxdart package.
_sendClientSubject.stream.delay(const Duration(hours: 1)).asyncMap((value) {
// do some operation
}).listen((value) {
// do nothing
});

misleading concept of future and async programming in flutter

I found it a bit confused with the concept of Future and async programming.
By definition, Future is a type that async function will return in Future.
The purpose is that we want the program to keep running while it is still waiting for the result of the async function.
What I dont understand is that, every often/always, I saw people using async with await which stop proceeding the program until it gets the result from async function called.
Arent we come to full circle? At first, async comes in for the situation that we dont want to wait for program taking time. But now, we use async with await in which we wait until the result is there
It is not always necessary to use await with a future. await can be used if you want to do further processing with the data.
Example:
Future<int> _getInt()async{
Future.delay(Duration(seconds:3)); //simulating network delay
return 7;
}
void _add() async{
int res = await _getInt() + 10; //need to await because we are going to use a future variable
_putInt(res); //not nesscary to await if you don't want to handle the response
/* Ex: var result = await _putInt(); // if you want to handel the response
if (result.statusCode==200){
// handle success
}else{
// handle error
}*/
}
Future _putInt(int number)async{
var res = await http.post('url',body:{'data':number});
return res;
}
Well, your institution is right, we use Future and async as it is nonblocking and follows an event loop approach, meaning there is a callback to the Future when it is ready to execute.
Coming to your point, I have done this myself a lot of time. And neither approach is wrong.
But when it comes to Flutter, it is in your best interest that you don't do anything else when running an async function because dart is single-threaded.
This can be blocking sometimes depending on the work of the function.
This can also be simply for UX as some data would be critical to your application and you shouldn't allow the user to do anything else until it is loaded.

Flutter send local notification by API in background

I have an API that I'm checking, and when the response changes I need to send a notification to the user. I would like to know how to do this without FCM Push Notifications.
I'm using flutter-local-notifications and background fetch (https://github.com/transistorsoft/flutter_background_fetch) to do it. On the background fetch docs it says that background fetch will do your function once every 15 minutes, which is good enough for me.
This is my initPlatformState():
Future<void> initPlatformState() async {
// Load persisted fetch events from SharedPreferences
SharedPreferences prefs = await SharedPreferences.getInstance();
String json = prefs.getString(EVENTS_KEY);
if (json != null) {
setState(() {
_events = jsonDecode(json).cast<String>();
});
}
// Configure BackgroundFetch.
BackgroundFetch.configure(
BackgroundFetchConfig(
minimumFetchInterval: 15,
stopOnTerminate: false,
enableHeadless: true,
forceReload: true,
startOnBoot: true,
),
_onBackgroundFetch)
.then((int status) {
print('[BackgroundFetch] SUCCESS: $status');
setState(() {
_status = status;
});
}).catchError((e) {
print('[BackgroundFetch] ERROR: $e');
setState(() {
_status = e;
});
});
// Optionally query the current BackgroundFetch status.
int status = await BackgroundFetch.status;
setState(() {
_status = status;
});
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
}
I'm assuming that what's in the function that gets called in the fetch isn't needed for the question.
I tried this on my phone and simulator, and I used Xcode -> Simulate Background Fetch and it ran properly. It also ran properly when I opened the app. Unfortunately, it didn't run after 15 minutes. Is there something I'm missing?
How would I change my code to make the background fetch to happen every 15 minutes?
Yes, I spent lot of time trying to solve this but was not successful so I switched, I guessed what you are trying to do is to handle your own notification without Firebase or from an API like me, well this is it, after my search I was able to do this with the help of work manager package. So easy to use and implement, try it.
https://pub.dev/packages/workmanager

(Flutter/Dart) Two async methods in initState not working

I have a function in my initState:
#override
void initState() {
_fetchListItems();
super.initState();
}
This function is very simple. It has two async await operations of sqflite, one of which waits for the other to complete in it:
_fetchListItems() async {
wait() async {
number = await db.getNumber(userId); }
await wait();
List rawFavouriteList = await db.getList(number);
setState((){
rawFavouriteList.forEach((item){
_favouriteList.add(Model.map(item));
}});
}
I have to wait for number to be fetched, only then I can fetch serialized List, which then I deserialize and populate then add to the List which is displayed in ListView.
The problem is, this is not working in initState. It's working fine when it's called through onPressed() of a button, but not in initState.
Points to Note:
1) There is no error being thrown
2) I have already tried more conservative alternatives by using await for even rawFavouriteListthrough a separate function like wait() before using setState() top populate the _favouriteList, even though it's working fine manually through buttons.
3) Everything works fine if I manually enter number value in the second database query and just remove the first query, i.e.
_fetchListItems() async {
List rawFavouriteList = await db.getList(42);
setState((){
rawFavouriteList.forEach((item){
_favouriteList.add(Model.map(item));
}});
}