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.