acincognito
acincognito

Reputation: 1743

flutter run function every x amount of seconds

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?

Upvotes: 94

Views: 115219

Answers (4)

Mohammed_Moulla
Mohammed_Moulla

Reputation: 55

THIS ANSWER FOR LONG PERIODS

if you want to do specific job in long intervals without using any library or Timer :

you can use shared preferences to store the last time the job done :

prefs.setString("last_time",TimeDate.now().toString());

and for each access to the homepage you can compare the value stored "last_time" with the current time minus the interval (let's say 1 day) :

DateTime today = DateTime.now();
DateTime time_ago = today.subtract(Duration(days:1));
String? last_time = prefs.getString("last_time");

if (last_time != null) {
    DateTime LC = DateTime.parse(last_time);
    if (LC.isBefore(time_ago)) { 
        //do job 
        prefs.setString("last_time",DateTime.now().toString());
    }
}

Upvotes: -1

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 658067

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

import 'dart:async';

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.

Upvotes: 223

Caroline T
Caroline T

Reputation: 11

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

Upvotes: 1

Jitesh Mohite
Jitesh Mohite

Reputation: 34270

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

Upvotes: 13

Related Questions