How do I run a reoccurring function, in Dart?

Dart

Dart Problem Overview


I'd like to run a function over and over, with a delay in between. How can I do this with Dart?

Dart Solutions


Solution 1 - Dart

You can use the Timer class to schedule one-shot and repeating functions.

Repeating

Here is how you run a repeating function:

import 'dart:async';
main() {
  const oneSec = Duration(seconds:1);
  Timer.periodic(oneSec, (Timer t) => print('hi!'));
}

The Timer takes two arguments, a duration and a function to run. The duration must be an instance of Duration. The callback must take a single parameter, the timer itself.

Canceling a repeating timer

Use timer.cancel() to cancel a repeating timer. This is one reason why timer is passed to the callback run from a repeating timer.


One-shot after a delay

To schedule a one-shot function after a delay (execute once, some time in the future):

import 'dart:async';
main() {
  const twentyMillis = Duration(milliseconds:20);
  Timer(twentyMillis, () => print('hi!'));
}

Notice the callback for a one-shot timer does not take a parameter.


One-shot as soon as possible

You can also request that a function is run as soon as possible, at least one event-loop tick in the future.

import 'dart:async';
main() {
  Timer.run(() => print('hi!'));
}

In HTML

Timers even work in HTML. In fact, window.setTimeout was removed, so Timer is the only way to run a function in the future.

Solution 2 - Dart

5 Sec Timer Example

bool isStopped = false; //global

sec5Timer() {
  Timer.periodic(Duration(seconds: 5), (timer) {
    if (isStopped) {
      timer.cancel();
    }
    print("Dekhi 5 sec por por kisu hy ni :/");
  });
}

Call from any function

sec5Timer(); 

Stop from any function

isStopped = true;

To dispose you can use this code or technique.

 @override
  void initState() {
    _timer = new Timer.periodic(widget.refreshRate, 
      (Timer timer) => _updateDisplayTime(inheritedWidget));
    super.initState();
  }

  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }

Solution 3 - Dart

https://api.dartlang.org/stable/1.24.3/dart-async/Stream/Stream.periodic.html

import 'dart:async';

StreamSubscription periodicSub;

void main() {
  periodicSub = new Stream.periodic(const Duration(milliseconds: 500), (v) => v)
      .take(10)
      .listen((count) => print('tick $count'));
}

or if the counter isn't required just

import 'dart:async';

StreamSubscription periodicSub;

void main() {
  periodicSub = new Stream.periodic(const Duration(milliseconds: 500))
      .take(10)
      .listen((_) => print('tick'));
}

Solution 4 - Dart

You can also use Future.delayed and await to delay execution:

Future<Null> delay(int milliseconds) {
  return new Future.delayed(new Duration(milliseconds: milliseconds));
}


main() async {
  await delay(500);
  print('Delayed 500 milliseconds');
}

Solution 5 - Dart

alternative;

import 'dart:async';

Timer interval(Duration duration, func) {
  Timer function() {
    Timer timer = new Timer(duration, function);

    func(timer);

    return timer;
  }

  return new Timer(duration, function);
}

void main() {
  int i = 0;

  interval(new Duration(seconds: 1), (timer) {
    print(i++);

    if (i > 5) timer.cancel();
  });
}

Solution 6 - Dart

Opposite to Timer.periodic and Stream.periodic posting my favorite way to handle such a tasks. The advantages:

  • the first cycle run instantly
  • the callback can work longer than interval without any reentrance headache
Completer<bool> periodic(Duration interval, Function(int cycle) callback) {
  final done = Completer<bool>();
      () async {
    var cycle = 0;
    while (!done.isCompleted) {
      try {
        await callback(cycle);
      } catch (e, s) {
        log("$e", stackTrace: s);
      }
      cycle++;
      await done.future
          .timeout(interval)
          .onError((error, stackTrace) => null);
    }
  }();
  return done;
}

main() {
  final task = periodic(Duration(seconds: 10), (cycle) async {
    /// do the periodic tasks here
  });

  /// main code here
  /// and when going to stop the above periodic call
  task.complete(true);
}

Solution 7 - Dart

Functionally identical code to JavaScript (setInterval, setTimeout, clearInterval and clearTimeout):

// ------------------------------
// Import:

import 'dart:async';

// ------------------------------
// Definitions:

void clearTimeout(Timer timer) {
  try {
    timer.cancel();
  } catch (e) {}
}

Timer setTimeout(VoidCallback fn, int millis) {
  Timer timer;
  if (millis > 0)
    timer = new Timer(new Duration(milliseconds: millis), fn);
  else
    fn();
  return timer;
}

void clearInterval(Timer timer) {
  try {
    timer.cancel();
  } catch (e) {}
}

Timer setInterval(VoidCallback fn, int millis) {
  Timer timer;
  if (millis > 0)
    timer = new Timer.periodic(new Duration(milliseconds: millis), (timer) {
      fn();
    });
  else
    fn(); // If millis input is too low, only run function once and stop
  return timer;
}

// ---------------------------------
// Example:

int myValue = 0;

Timer counter = setInterval((){ myValue++; }, 50);
setTimeout((){
    clearInterval(counter);
}, 5000);

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
QuestionSeth LaddView Question on Stackoverflow
Solution 1 - DartSeth LaddView Answer on Stackoverflow
Solution 2 - DartRafsan Uddin Beg RizanView Answer on Stackoverflow
Solution 3 - DartGünter ZöchbauerView Answer on Stackoverflow
Solution 4 - DartMatt S.View Answer on Stackoverflow
Solution 5 - DartAhmet ŞimşekView Answer on Stackoverflow
Solution 6 - DartAlexei VolkovView Answer on Stackoverflow
Solution 7 - DartJože VovkView Answer on Stackoverflow