Bidev
BeginnerAsync Programming

What's the difference between Timer and Future.delayed?

Short Answer

Future.delayed runs a callback once after a delay and resolves; Timer can either fire once (Timer()) or repeatedly (Timer.periodic()), and importantly gives you a handle you can explicitly cancel.

Future.delayed(duration, callback) is a one-shot delayed action expressed as a Future — convenient when you just need to await a pause or chain a delayed step into async code. It has no built-in way to cancel it once started.

Timer(duration, callback) does the same one-shot job but returns a Timer object with a .cancel() method, which matters when the delayed action might need to be aborted (e.g. a debounce timer that should reset if the user types again). Timer.periodic(duration, callback) repeats indefinitely until cancelled — the standard tool for polling or a repeating countdown, and one that must be cancelled in dispose() to avoid leaking.

Code Example

// One-shot, no cancellation needed
Future.delayed(const Duration(seconds: 2), () => print('done'));

// Cancellable debounce timer
Timer? _debounce;
void onSearchChanged(String query) {
  _debounce?.cancel();
  _debounce = Timer(const Duration(milliseconds: 300), () => search(query));
}

Common Mistakes

  • ×Using Future.delayed for a debounce pattern where you need to cancel a pending call — only Timer can be cancelled.
  • ×Forgetting to cancel a Timer.periodic in dispose(), leaking a repeating callback indefinitely.