【发布时间】:2023-02-14 03:58:34
【问题描述】:
如何制作一个计时器,使其速度每分钟增加一次,即计时器持续时间在 Flutter 中每 1 分钟减少一次?
【问题讨论】:
-
使用Timer构造函数(每次减少
duration),而不是Timer.periodic -
你能详细说明一下吗?也许是一个例子!
-
你用 60 秒
duration调用Timer,当callback完成时你用 58 秒再次调用它,然后用 56 等
如何制作一个计时器,使其速度每分钟增加一次,即计时器持续时间在 Flutter 中每 1 分钟减少一次?
【问题讨论】:
duration),而不是Timer.periodic
duration 调用 Timer,当 callback 完成时你用 58 秒再次调用它,然后用 56 等
如 cmets 部分所述,您可以使用递归函数来完成这些工作。
import 'dart:async';
void main() {
launchTimer(Duration(seconds: 2), minDuration: Duration(milliseconds: 300));
}
void launchTimer(Duration duration, {Duration? minDuration}) => Timer(duration, () {
final wantedDuration = duration - Duration(milliseconds: 300);
if (minDuration != null && wantedDuration < minDuration) {
print('minDuration');
launchTimer(minDuration, minDuration: minDuration);
} else {
print('wantedDuration');
launchTimer(wantedDuration, minDuration: minDuration);
}
});
在这个例子中,我有一个 minDuration 限制,以避免不必要的行为。
您可以将此代码导入 dart pad 中进行尝试 :)
【讨论】:
这是一个 Timer 实现,它的行为类似于普通的周期性 Timer 但允许回调修改周期(甚至回调):
import 'dart:async';
class VariableTimer implements Timer {
void Function(VariableTimer) callback;
Duration period;
Timer? _timer;
int _tick = 0;
VariableTimer(Duration initialPeriod, this.callback)
: period = initialPeriod {
_timer = Timer(initialPeriod, _onTimer);
}
@override
bool get isActive => _timer != null;
@override
int get tick => _tick;
@override
void cancel() {
_timer?.cancel();
_timer = null;
}
void _onTimer() {
var stopwatch = Stopwatch()..start();
_tick += 1;
callback(this);
if (!isActive) {
return;
}
var adjustedPeriod = _max(Duration.zero, period - stopwatch.elapsed);
_timer = Timer(adjustedPeriod, _onTimer);
}
}
Duration _max(Duration duration1, Duration duration2) =>
duration1 >= duration2 ? duration1 : duration2;
创建周期性 Timer 的示例用法,最初每 10 秒触发一次,每分钟提前一秒触发,并在周期达到 0 时停止:
void main() {
const oneMinute = Duration(minutes: 1);
var nextUpdate = DateTime.now().add(oneMinute);
VariableTimer(const Duration(seconds: 10), (timer) {
print(DateTime.now());
var timeToNext = nextUpdate.difference(DateTime.now());
if (timeToNext <= Duration.zero) {
nextUpdate = nextUpdate.add(oneMinute);
timer.period -= const Duration(seconds: 1);
if (timer.period <= Duration.zero) {
timer.cancel();
}
}
});
}
【讨论】:
你可以只用你的最小周期创建一个Timer.periodic,并在回调中使用静态计数器来标记该可变周期的倍数。这样做的好处是可以很容易地扩展到在不同时期运行的任意数量的任务——所有任务都由同一个计时器驱动。
import 'dart:async';
import 'dart:math';
const int minPeriod=1;
const int maxPeriod=10;
const double decreaseRate=0.1;
int variablePeriodSeconds(int t) {
var p=decreaseRate*t;
return max(maxPeriod-p.floor(),minPeriod); // simple linear decrease
}
void main() {
int tTick=0;
int tTock=0;
final Duration minDuration = Duration(seconds: minPeriod);
Timer timer = Timer.periodic(minDuration, (Timer timer) {
print('tick');
if(tTick-tTock >= variablePeriodSeconds(tTick)){
print("TOCK!");
tTock=tTick;
}
tTick++;
});
}
【讨论】: