flutter run function every x amount of seconds

DartFlutter

Dart 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

enter image description here

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionacincognitoView Question on Stackoverflow
Solution 1 - DartGünter ZöchbauerView Answer on Stackoverflow
Solution 2 - DartJitesh MohiteView Answer on Stackoverflow
Solution 3 - DartCaroline TView Answer on Stackoverflow