编辑:请注意,原始答案中建议的 API 现在标记为 @ObsoleteCoroutineApi:
Ticker 通道目前未与结构化并发集成,其 api 将在未来发生变化。
您现在可以使用Flow API 创建您自己的代码流:
import kotlin.time.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun tickerFlow(period: Duration, initialDelay: Duration = Duration.ZERO) = flow {
delay(initialDelay)
while (true) {
emit(Unit)
delay(period)
}
}
您可以以与当前代码非常相似的方式使用它:
tickerFlow(Duration.seconds(5))
.map { LocalDateTime.now() }
.distinctUntilChanged { old, new ->
old.minute == new.minute
}
.onEach {
setDateTime(it)
}
.launchIn(viewModelScope) // or lifecycleScope or other
如果您不想要实验性的Duration API,也可以使用Long 毫秒。
注意:使用此处编写的代码,tickerFlow 未考虑处理元素所花费的时间,因此延迟可能不是定期的(这是元素处理之间的延迟)。如果您希望代码独立于每个元素的处理进行滴答,您可能需要使用buffer 或专用线程(例如通过flowOn)。
原答案
我相信它仍处于试验阶段,但您可以使用 TickerChannel 来生成每 X 毫秒的值:
val tickerChannel = ticker(delayMillis = 60_000, initialDelayMillis = 0)
repeat(10) {
tickerChannel.receive()
val currentTime = LocalDateTime.now()
println(currentTime)
}
如果您需要在“订阅”为每个“滴答”做某事的同时继续工作,您可以launch 一个后台协程,该协程将从该频道读取并做您想做的事情:
val tickerChannel = ticker(delayMillis = 60_000, initialDelayMillis = 0)
launch {
for (event in tickerChannel) {
// the 'event' variable is of type Unit, so we don't really care about it
val currentTime = LocalDateTime.now()
println(currentTime)
}
}
delay(1000)
// when you're done with the ticker and don't want more events
tickerChannel.cancel()
如果你想从循环内部停止,你可以简单地跳出它,然后取消通道:
val ticker = ticker(500, 0)
var count = 0
for (event in ticker) {
count++
if (count == 4) {
break
} else {
println(count)
}
}
ticker.cancel()