flutter run function every x amount of seconds
DartFlutterDart Problem Overview
inside my flutter app I want to check my api every 10 seconds. I found this post to run a function every x amount of time and did the following:
class _MainPage extends State<MainPage> {
int starter = 0;
void checkForNewSharedLists(){
// do request here
setState((){
// change state according to result of request
});
}
Widget build(BuildContext context) {
Timer.periodic(Duration(seconds: 15), (Timer t) => checkForNewSharedLists());
}
}
Unfortunately the requests pile up: after restarting the app on the first "round" there are two request to the api, the second round it's four requests, the third it's eight and so on...
Does anybody know how to fix this?
Dart Solutions
Solution 1 - Dart
build()
can and usually will be called more than once and every time a new Timer.periodic
is created.
You need to move that code out of build()
like
Timer? timer;
@override
void initState() {
super.initState();
timer = Timer.periodic(Duration(seconds: 15), (Timer t) => checkForNewSharedLists());
}
@override
void dispose() {
timer?.cancel();
super.dispose();
}
Even better would be to move out such code from widgets entirely in an API layer or similar and use a StreamBuilder
to have the view updated in case of updated data.
Solution 2 - Dart
Use Cron lib which will be run periodically, but there is a difference between Timer and Cron,
Timer: It's running a task on given specific time intervals whether it is seconds, minutes, or hours.
Cron: It's used for more complex time intervals, eg: if a task needs to be run on a specific time of an hour. let's see the diagram
The above diagram has an asterisk that represents a number that appears in a specific position.
import 'package:cron/cron.dart';
main() {
var cron = new Cron();
cron.schedule(new Schedule.parse('*/3 * * * *'), () async {
print('every three minutes');
});
cron.schedule(new Schedule.parse('8-11 * * * *'), () async {
print('between every 8 and 11 minutes');
});
}
The above examples are taken from the repository which pretty well explains that the first '*' represents minutes, similar for the hour and so on as shown in the diagram.
Another example of the hour would be Schedule.parse(* 1,2,3,4 * * *)
, This schedule will run every minute every day during the hours of 1 AM, 2 AM, 3 AM, and 4 AM.
for more reference https://code.tutsplus.com/tutorials/scheduling-tasks-with-cron-jobs--net-8800
Solution 3 - Dart
Timer works fine, but you can also use Stream to execute a function periodicly:
final Stream _myStream =
Stream.periodic(const Duration(seconds: x), (int count) {
// Do something and return something here
});
see: https://api.flutter.dev/flutter/dart-async/Stream/Stream.periodic.html
I was looking for code to run a function every n amount of seconds for x seconds in total. Also I added functionality to cancel the timer if the periodic Function returns a success before the total timer elapsed. So here is how to solve that:
bool success = false;
bool done = false;
Future.delayed(const Duration(seconds: n), () {
done = true;
print("Timeout");
});
await Stream.periodic(const Duration(seconds: x)).takeWhile((_) => !done).forEach((_) async
{
success = await FunctionYouWantToExecutePeriodicly();
done = success; // only if you want to finish the function earlier
});