Flutteronic method of scheduling code to run on the next event loop - flutter

This is common in other languages. setTimeout(fn, 0) in JavaScript, and DispatchQueue.main.async() {} in Swift.
How best to do this in Flutter?
I have used Future.delayed(Duration.zero).then(fn), but I don't like it because like JS's setTimeout and unlike swifts DispatchQueue.main.async() {} it doesn't really express the intent, only the behaviour. Is there a way of doing this that is the correct way to do this in Flutter.

Use addPostFrameCallback
WidgetsBinding.instance
.addPostFrameCallback((timestamp) {
print("I'm running after the frame was built");
});
This will cause your callback function to run right after flutter has finished building the current frame.
Note that the callback will only run once, if you want to reschedule it for each build, set the callback at the beginning of the build function.
#override
Widget build(BuildContext context) {
WidgetsBinding.instance
.addPostFrameCallback((timestamp) {
print("I'm running after the frame was built");
});
return Container();
}

You can also use Timer from flutter.
Example
Timer(Duration(seconds: 1), () {
print('hai');
});
Duration gives you options with seconds,milliseconds,days,hours,minutes.
You can achieve setInterval also using Timer
Timer.periodic(Duration(seconds: 1), (Timer timer) {
print('hai');
});
But keep in mind that to cancel the timer on dispose.This would save you from hitting memory
Timer timer;
timer = Timer(Duration(seconds: 1), () {
print('hai');
});
void dispose() {
timer.cancel();
}

Related

How to call any method or page after every 1 second?

Whenever my home page was reloaded my data was updated but I want to reflect data instantly.
That's why I need a method that can refresh my page or method after every 1 second(flutter).
pls, help me.
You can use the Timer.periodic to run a method every Duration you specify and using StatefulWidgetn you can run it in initState like this:
#override
void initState() {
Timer.periodic(Duration(seconds: 1), (timer) {
print("this will execute every second");
});
super.initState();
}
change the print with your method.
in Your init state call the Timer like this
#override
void initState() {
new Timer.periodic(Duration(seconds: 1), (Timer t) => YourMethod());//api call
super.initState();
}
this will update your full screen
This work's for me :smile:
Timer.periodic(Duration(milliseconds: 2200),
(timer) {
'Your Method'
debugPrint('Timer 1 sec ${timer.tick.toString()}');
});

Dart/Flutter Yield state after timer

I am using flutter_bloc and I am not sure how to yield state from within a callback.
Am trying to start timer and return a new state after a pause. Reason I am using a timer is to get the ability to cancel previous timer so it always returns a new state after an idle state.
#override
Stream<VerseState> mapEventToState(
VerseEvent event,
) async* {
if (event is ABCEvent) {
Timer(const Duration(seconds: 3), () {
print("Here");
_onTimerEnd(); // adding yield here returns an error.
})
}
Stream<XYZState> _onTimerEnd() async* {
print("Yielding a state");
yield myNewState();
}
I can see that the code is getting inside the timer callback as I can see the print statements in the callback but not in the timerEnd() method.
State should be yielded by the stream used in bloc that you are current working on. Like
mapEventToState

The periodic timer is duplicated in initState ()

When switching to another page, a periodic timer is started in initState (). But it is duplicated.
Or I am making a wrong transition to another page. Or initState () is doubled.
Code for moving from one page to another:
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new MapPage(phone: _phone)));
Timer call:
#override
void initState() {
super.initState();
_timerSendPointStart = Timer.periodic(Duration(seconds: 10), (timer) {
setState(() {
makePoint();
});
});
}
Can you please tell me where the error is and how to fix it?
use onWillPop() life cycle hook to stop the timer/delete the timer before navigating to another screen. otherwise, you will get the timer's overflow.
It's also good to cancel the timer in the dispose() function.

Is there a way I can continuously change some text in certain interval of time?

In some area, I want a list of objects to be continuously appeared replacing the previous one in a gap of 2 secs. And in that interval I wanna do some logic.
I tried Flutter.delayed but it doesn't work accordingly in a while loop.
In your initState method, use Timer.periodic(...)
#override
void initState() {
super.initState();
// this code runs after every 2 seconds.
Timer.periodic(Duration(seconds: 2), (timer) {
if (_someCondition) {
timer.cancel(); // if you want to stop this loop use cancel
}
setState(() {
_string = "new value"; // your logic here
});
});
}
Create a timer and put your logic in the function that handles the timer event.
...
...
initstate() {
Timer.periodic( Duration(seconds: 2), (Timer t) {
setState(() => displayTheNextElementOfTheList());
...
//your logic here
});
...
}

Flutter - Background Service in Dart (only when app is visible)

I need a background service in flutter, that makes very minute a http.get(...)
This service should run in the background, while the app is running. If the app is closed, the background service should stopp also. When the app gets started, the background service should also get started.
I can only find packages, that provide a background service, that also runs, when the app is closed - like this example: https://medium.com/flutter-io/executing-dart-in-the-background-with-flutter-plugins-and-geofencing-2b3e40a1a124
Maybe what I'm looking for is not called "background-service"?
Here is some code, I want to run in this background service/task...
Timer.periodic(Duration(seconds: 60), (Timer t) => checkForUpdates());
I came across the same Problem. Timer.periodic keeps running in the background for an uncontrollable time after leaving the app. My solution is something like this:
class CollectStampsState extends State<CollectStamps> with WidgetsBindingObserver {
Timer timer;
...
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state != AppLifecycleState.resumed) {
timer.cancel();
} else {
if (!timer.isActive) {
timer = Timer.periodic(Duration(seconds: 30), (Timer t) => yourFunction());
}
}
#override
void initState() {
super.initState();
timer = Timer.periodic(Duration(seconds: 30), (Timer t) => yourFunction());
WidgetsBinding.instance.addObserver(this);
}
#override
void dispose() {
timer?.cancel();
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
#override
Widget build(BuildContext context) {
...
}
}
You can also save the AppLifecycleState, if you want to use it in other places, or change the behavior for different AppLifecycleStates. But like this, the timer is only active, when the app is in the foreground. As soon as it's in the Background, the timer is canceled.