如何处理 "onCancel" 的 Timer.periodic 或 Stream.periodic
How to handle "onCancel" of Timer.periodic or Stream.periodic
每当用户想要播放一些音频时,首先我要等待 5 秒,然后每秒执行一个动作。每当用户按下播放按钮时,我都会调用 onPlay()
方法。我的第一次尝试是这样的:
Timer? _timer; // I might need to cancel timer also when the user pauses playback by pause button or something
void onPlay() async {
int _secondsLeft = 5;
_timer = await Timer.periodic(const Duration(seconds: 1), (_) {
if (_secondsLeft == 0) _timer?.cancel();
_textToSpeech.speak(_secondsLeft.toString());
--_secondsLeft;
});
audio.play(_curSong);
}
此尝试无法正常工作,因为 audio.play()
运行 在计时器初始化后立即未完成。我找到 How to make Timer.periodic cancel itself when a condition is reached? 并使用其中一个答案来改进我的代码,如下所示:
StreamSubscription? _timer;
void onPlay() async {
int _secondsLeft = 5;
_timer = await Stream.periodic(const Duration(seconds: 1))
.takeWhile((_) => _secondsLeft > 0)
.forEach((_) {
_textToSpeech.speak(_secondsLeft.toString());
--_secondsLeft;
});
audio.play(_curSong);
}
这样效果更好,但是如果用户在初始阶段切换到不同的歌曲或暂停播放,_timer?.cancel()
只会取消流,因此它之后的所有内容 (audio.play(_curSong)
) 仍然运行。但我想不仅要取消流,还要跳过 audio.play()
功能。所以我想 运行 audio.play()
只有在 Timer/Stream 正确完成而没有取消之后。
是否有任何选项可以处理 Stream.periodic 或 Timer.periodic 取消操作(“onCancel”)?或者有更好的方法来处理这个特定任务吗?
快到了。您在 .forEach
上的等待实际上 returns 为空。所以据我所知,没有 StreamSubscription。
可能是您问题的简单解决方案的回调是 listen
方法中的可选 onDone
。 Stream被取消时不会被调用
import 'dart:async';
void main() async {
onPlay();
await Future.delayed(Duration(seconds: 2));
// Uncomment me to test it
// _timer?.cancel();
}
StreamSubscription? _timer;
void onPlay() {
int _secondsLeft = 5;
_timer = Stream.periodic(const Duration(seconds: 1))
.takeWhile((_) => _secondsLeft > 0)
.listen((event) {
print(_secondsLeft.toString());
--_secondsLeft;
}, onDone: () {
print("It's show time!");
});
}
你已经很接近了,你只需要在定时器倒计时时播放歌曲,同时取消定时器。
所以:
Timer? _timer;
void onPlay() async {
int _secondsLeft = 5;
_timer = await Timer.periodic(const Duration(seconds: 1), (_) {
if (_secondsLeft == 0) {
_timer?.cancel();
audio.play(_curSong);
} else {
_textToSpeech.speak(_secondsLeft.toString());
--_secondsLeft;
}
});
}
(请注意,这并没有说 zero
,您原来的位置。而是播放音乐。如果您想让它说零,请将 == 0
更改为 < 0
.)
用这种写法,取消定时器会停止播放歌曲。
每当用户想要播放一些音频时,首先我要等待 5 秒,然后每秒执行一个动作。每当用户按下播放按钮时,我都会调用 onPlay()
方法。我的第一次尝试是这样的:
Timer? _timer; // I might need to cancel timer also when the user pauses playback by pause button or something
void onPlay() async {
int _secondsLeft = 5;
_timer = await Timer.periodic(const Duration(seconds: 1), (_) {
if (_secondsLeft == 0) _timer?.cancel();
_textToSpeech.speak(_secondsLeft.toString());
--_secondsLeft;
});
audio.play(_curSong);
}
此尝试无法正常工作,因为 audio.play()
运行 在计时器初始化后立即未完成。我找到 How to make Timer.periodic cancel itself when a condition is reached? 并使用其中一个答案来改进我的代码,如下所示:
StreamSubscription? _timer;
void onPlay() async {
int _secondsLeft = 5;
_timer = await Stream.periodic(const Duration(seconds: 1))
.takeWhile((_) => _secondsLeft > 0)
.forEach((_) {
_textToSpeech.speak(_secondsLeft.toString());
--_secondsLeft;
});
audio.play(_curSong);
}
这样效果更好,但是如果用户在初始阶段切换到不同的歌曲或暂停播放,_timer?.cancel()
只会取消流,因此它之后的所有内容 (audio.play(_curSong)
) 仍然运行。但我想不仅要取消流,还要跳过 audio.play()
功能。所以我想 运行 audio.play()
只有在 Timer/Stream 正确完成而没有取消之后。
是否有任何选项可以处理 Stream.periodic 或 Timer.periodic 取消操作(“onCancel”)?或者有更好的方法来处理这个特定任务吗?
快到了。您在 .forEach
上的等待实际上 returns 为空。所以据我所知,没有 StreamSubscription。
可能是您问题的简单解决方案的回调是 listen
方法中的可选 onDone
。 Stream被取消时不会被调用
import 'dart:async';
void main() async {
onPlay();
await Future.delayed(Duration(seconds: 2));
// Uncomment me to test it
// _timer?.cancel();
}
StreamSubscription? _timer;
void onPlay() {
int _secondsLeft = 5;
_timer = Stream.periodic(const Duration(seconds: 1))
.takeWhile((_) => _secondsLeft > 0)
.listen((event) {
print(_secondsLeft.toString());
--_secondsLeft;
}, onDone: () {
print("It's show time!");
});
}
你已经很接近了,你只需要在定时器倒计时时播放歌曲,同时取消定时器。 所以:
Timer? _timer;
void onPlay() async {
int _secondsLeft = 5;
_timer = await Timer.periodic(const Duration(seconds: 1), (_) {
if (_secondsLeft == 0) {
_timer?.cancel();
audio.play(_curSong);
} else {
_textToSpeech.speak(_secondsLeft.toString());
--_secondsLeft;
}
});
}
(请注意,这并没有说 zero
,您原来的位置。而是播放音乐。如果您想让它说零,请将 == 0
更改为 < 0
.)
用这种写法,取消定时器会停止播放歌曲。