1

My stopwatch is running 0.5x slower than actual time (e.g. while the real time is 1 minute, the stopwatch shows ~34 seconds).

Here is the Provider code:

class TimerState extends ChangeNotifier { 
   late String _stringTimer; 
   late Duration _duration; 
   Timer? _timer; 
  
   TimerState() { 
     _stringTimer = '00:00.00'; 
     _duration = const Duration(); 
   } 
  
   String get get => _stringTimer; 
  
   void start() { 
     _timer = Timer.periodic(const Duration(milliseconds: 1), (_) => _addTime()); 
   } 
  
   void _addTime() { 
     _duration = Duration(milliseconds: _duration.inMilliseconds + 1); 
     _formattedTimer(); 
   } 
  
   void _formattedTimer() { 
     String twoDigits(int n) => n.toString().padLeft(2, '0'); 
     final milliseconds = twoDigits((_duration.inMilliseconds.remainder(1000) / 10).floor()); 
     final seconds = twoDigits(_duration.inSeconds.remainder(60)); 
     final minutes = twoDigits(_duration.inMinutes.remainder(60)); 
     _stringTimer = '$minutes:$seconds.$milliseconds'; 
     notifyListeners(); 
   } 
 }

1 Answer 1

3

Your approach adds the timer interval (1ms) on each timer event. That is a bad approach because it assumes that your timer fires exactly on every millisecond with no room for error. You also will lose time if any timer events are missed (which might happen if you ever do work that takes longer than 1ms). Error will accumulate.

Also note that 1ms is very short. Redrawing your widget every millisecond would be updating it at a rate of 1000 frames per second.

A much better approach would be to record the start time and, on each timer event, compute the difference from DateTime.now() to the start time (e.g. var elapsed = DateTime.now().difference(startTime);). That will prevent error from accumulating. Better yet, use a Stopwatch object which does that for you.

You also should pick a more reasonable timer interval; picking a rate faster than your screen's refresh rate is wasteful.

Sign up to request clarification or add additional context in comments.

8 Comments

Do you think 1ms can cause performance problems? because in my case it is really necessary
@chrisrn Why is it necessary? A 1ms timer itself is not necessarily a problem, but all of the work that you currently do on each timer event is completely wasted.
And the fact that you're dropping half of your timer events is evidence that, yes, you have a performance problem by doing too much work for a 1ms interval.
Is for accurately determine the score in a game. So, if the problem is in the process that it makes every ms, would the Stopwatch class be a solution?
@Dani If you want to count some number of seconds, you should still use 2 DateTimes. For example, to count 10 seconds, you'd start form var now = DateTime.now(); and end at now.add(Duration(seconds: 10)).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.