Rom*_*ych 5 kotlin kotlinx.coroutines
I want to implement timer using Kotlin coroutines, something similar to this implemented with RxJava:
Flowable.interval(0, 5, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.map { LocalDateTime.now() }
.distinctUntilChanged { old, new ->
old.minute == new.minute
}
.subscribe {
setDateTime(it)
}
Run Code Online (Sandbox Code Playgroud)
It will emit LocalDateTime every new minute.
Jof*_*rey 14
我相信它仍处于试验阶段,但是您可以使用TickerChannel每X 毫秒产生一个值:
val tickerChannel = ticker(delayMillis = 60_000, initialDelayMillis = 0)
repeat(10) {
tickerChannel.receive()
val currentTime = LocalDateTime.now()
println(currentTime)
}
Run Code Online (Sandbox Code Playgroud)
如果您需要在“订阅”为每个“滴答”做某事的同时继续进行工作launch,则可以从该频道读取后台协程并做您想做的事情:
val tickerChannel = ticker(delayMillis = 60_000, initialDelayMillis = 0)
launch {
for (event in tickerChannel) { // event is of type Unit, so we don't really care about it
val currentTime = LocalDateTime.now()
println(currentTime)
}
}
// when you're done with the ticker and don't want more events
tickerChannel.cancel()
Run Code Online (Sandbox Code Playgroud)
Ste*_*nke 11
Kotlin Flows 的一种非常务实的方法可能是:
// Create the timer flow
val timer = (0..Int.MAX_VALUE)
.asSequence()
.asFlow()
.onEach { delay(1_000) } // specify delay
// Consume it
timer.collect {
println("bling: ${it}")
}
Run Code Online (Sandbox Code Playgroud)
您可以像这样创建倒数计时器
GlobalScope.launch(Dispatchers.Main) {
val totalSeconds = TimeUnit.MINUTES.toSeconds(2)
val tickSeconds = 1
for (second in totalSeconds downTo tickSeconds) {
val time = String.format("%02d:%02d",
TimeUnit.SECONDS.toMinutes(second),
second - TimeUnit.MINUTES.toSeconds(TimeUnit.SECONDS.toMinutes(second))
)
timerTextView?.text = time
delay(1000)
}
timerTextView?.text = "Done!"
}
Run Code Online (Sandbox Code Playgroud)
另一种可能的解决方案是可重用的 kotlin 扩展 CoroutineScope
fun CoroutineScope.launchPeriodicAsync(
repeatMillis: Long,
action: () -> Unit
) = this.async {
if (repeatMillis > 0) {
while (isActive) {
action()
delay(repeatMillis)
}
} else {
action()
}
}
Run Code Online (Sandbox Code Playgroud)
然后用作:
var job = CoroutineScope(Dispatchers.IO).launchPeriodicAsync(100) {
//...
}
Run Code Online (Sandbox Code Playgroud)
然后打断它:
job.cancel()
Run Code Online (Sandbox Code Playgroud)
这是使用 Kotlin Flow 的可能解决方案
fun tickFlow(millis: Long) = callbackFlow<Int> {
val timer = Timer()
var time = 0
timer.scheduleAtFixedRate(
object : TimerTask() {
override fun run() {
try { offer(time) } catch (e: Exception) {}
time += 1
}
},
0,
millis)
awaitClose {
timer.cancel()
}
}
Run Code Online (Sandbox Code Playgroud)
用法
val job = CoroutineScope(Dispatchers.Main).launch {
tickFlow(125L).collect {
print(it)
}
}
...
job.cancel()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3068 次 |
| 最近记录: |