@@ -39,6 +39,8 @@ final class PausableTimer implements Timer {
3939 /// When the timer expires, this stopwatch is set to null.
4040 Stopwatch ? _stopwatch = clock.stopwatch ();
4141
42+ final bool _periodic;
43+
4244 /// The currently active [Timer] .
4345 ///
4446 /// This is null whenever this timer is not currently active.
@@ -61,45 +63,91 @@ final class PausableTimer implements Timer {
6163 /// should make sure the timer wasn't cancelled before calling this function.
6264 void _startTimer () {
6365 assert (_stopwatch != null );
64- _timer = _zone.createTimer (
65- _originalDuration - _stopwatch! .elapsed,
66- () {
67- _tick++ ;
68- _timer = null ;
69- _stopwatch = null ;
70- _zone.run (_callback! );
71- },
72- );
66+
67+ if (_periodic && _stopwatch! .elapsed == Duration .zero) {
68+ _timer = _zone.createPeriodicTimer (
69+ duration,
70+ (Timer timer) {
71+ _tick++ ;
72+ _zone.run (_callback! );
73+ _stopwatch = clock.stopwatch ();
74+ _stopwatch! .start ();
75+ },
76+ );
77+ } else {
78+ _timer = _zone.createTimer (
79+ duration - _stopwatch! .elapsed,
80+ () {
81+ _tick++ ;
82+ if (_periodic) {
83+ reset ();
84+ } else {
85+ _timer = null ;
86+ _stopwatch = null ;
87+ }
88+ _zone.run (_callback! );
89+ },
90+ );
91+ }
92+
7393 _stopwatch! .start ();
7494 }
7595
76- /// Creates a new timer.
96+ /// Creates a new pausable timer.
7797 ///
7898 /// The [callback] is invoked after the given [duration] , but can be [pause] d
7999 /// in between or [reset] . The [elapsed] time is only accounted for while the
80- /// timer [isActive] .
100+ /// timer is active.
101+ ///
102+ /// The timer is paused when created, and must be [start] ed manually.
103+ ///
104+ /// The [duration] must be equals or bigger than [Duration.zero] .
105+ /// If it is [Duration.zero] , the [callback] will still not be called until
106+ /// the timer is [start] ed.
107+ PausableTimer (this .duration, void Function () callback)
108+ : assert (duration >= Duration .zero),
109+ _zone = Zone .current,
110+ _periodic = false {
111+ _callback = _zone.bindCallback (callback);
112+ }
113+
114+ /// Creates a new repeating pausable timer.
115+ ///
116+ /// The [callback] is invoked repeatedly with [duration] intervals until
117+ /// canceled with the [cancel] function, but can be [pause] d
118+ /// in between or [reset] . The [elapsed] time is only accounted for while the
119+ /// timer is active.
120+ ///
121+ /// The timer is paused when created, and must be [start] ed manually.
122+ ///
123+ /// The exact timing depends on the underlying timer implementation.
124+ /// No more than `n` callbacks will be made in `duration * n` time,
125+ /// but the time between two consecutive callbacks
126+ /// can be shorter and longer than `duration` .
81127 ///
82- /// The timer [isPaused] when created, and must be [start] ed manually.
128+ /// In particular, an implementation may schedule the next callback, e.g.,
129+ /// a `duration` after either when the previous callback ended,
130+ /// when the previous callback started, or when the previous callback was
131+ /// scheduled for - even if the actual callback was delayed.
83132 ///
84133 /// The [duration] must be equals or bigger than [Duration.zero] .
85134 /// If it is [Duration.zero] , the [callback] will still not be called until
86135 /// the timer is [start] ed.
87- PausableTimer ( Duration duration, void Function () callback)
136+ PausableTimer . periodic ( this . duration, void Function () callback)
88137 : assert (duration >= Duration .zero),
89- _originalDuration = duration ,
90- _zone = Zone .current {
138+ _zone = Zone .current ,
139+ _periodic = true {
91140 _callback = _zone.bindCallback (callback);
92141 }
93142
94143 /// The original duration this [Timer] was created with.
95- Duration get duration => _originalDuration;
96- final Duration _originalDuration;
144+ final Duration duration;
97145
98146 /// The time this [Timer] have been active.
99147 ///
100148 /// If the timer is paused, the elapsed time is also not computed anymore, so
101149 /// [elapsed] is always less than or equals to the [duration] .
102- Duration get elapsed => _stopwatch? .elapsed ?? _originalDuration ;
150+ Duration get elapsed => _stopwatch? .elapsed ?? duration ;
103151
104152 /// True if this [Timer] is armed but not currently active.
105153 ///
0 commit comments