Creating a periodic Timer

Notes

One possible way of updating the UI at regular intervals is to configure and use a Timer inside initState():

class _StopwatchState extends State<Stopwatch> {
  late DateTime _initialTime;
  late final Timer _timer;
  Duration _elapsed = Duration.zero;
  @override
  void initState() {
    super.initState();
    _initialTime = DateTime.now();
    _timer = Timer.periodic(Duration(milliseconds: 50), (_) {
      final now = DateTime.now();
      setState(() {
        _elapsed = now.difference(_initialTime);
      });
    });
  }
  // don't forget to cancel the timer on dispose!
  ...
}

Though as we will see this is not precise and has some drawbacks in this use case.


Note the usage of the late keyword. This was added with Null Safety support in Dart, and it's useful when variable initialization happens after declaration, but the variable is guaranteed to be non-null when it's used.

This is true for the _initialTime and _timer variables in this case because initState() is guaranteed to be called before the build() and dispose() methods.

The alternative would be to declare it like this:

final Timer? _timer;

But then it would have to be used like this:

  @override
  void dispose() {
    // note use of `?.` because _timer is *nullable*
    _timer?.cancel();
    super.dispose();
  }

Take-away: use late when declaring variables that are set to a non-null value in initState().

Discussion

1 comments