协程没有内置的重启操作,但您可以只cancel() 已经在运行一个,然后再次调用launch()(或任何其他协程构建器)以从头开始。
但是...对于您的具体情况,我建议阅读reactive programming,尤其是:RxJava 或Kotlin flows。它们是专门为解决这类问题而发明的。
查看这个使用流的示例:
suspend fun main() {
// simulate slider position changes
val sliderFlow = flow {
emit(1)
delay(50)
emit(2)
delay(50)
emit(3)
delay(50)
emit(4)
delay(800)
emit(5)
delay(1500)
emit(6)
}
sliderFlow.collectLatest { drawGraph(it) }
}
suspend fun drawGraph(input: Int) {
println("started drawing $input...")
try {
delay(1000) // simulate drawing
} catch (e: CancellationException) {
println("cancelled drawing $input")
throw e
}
println("ended drawing $input")
}
sliderFlow 是滑块位置流(为测试目的而创建)。对于每个新位置 drawGraph() 都会被调用,这需要 1000 毫秒才能完成。由于我们只对最新位置感兴趣,因此我们使用collectLatest(),如果有新值到达,它会自动取消对值的处理。它产生这个输出:
started drawing 1...
cancelled drawing 1
started drawing 2...
cancelled drawing 2
started drawing 3...
cancelled drawing 3
started drawing 4...
cancelled drawing 4
started drawing 5...
ended drawing 5
started drawing 6...
ended drawing 6
我们可以看到,只有 5 和 6 完成了,其余的被取消了,因为在 drawGraph() 能够完成之前发出了新的滑块值。
此外,如果滑块可以移动得非常快,那么我们可能不想为每个新值开始绘制,因为那样我们将开始绘制只是在几毫秒后取消。在这种情况下,我们可以使用debounce(),它会在指定的时间内等待值“稳定”:
sliderFlow
.debounce(100)
.collectLatest { drawGraph(it) }
输出:
started drawing 4...
cancelled drawing 4
started drawing 5...
ended drawing 5
started drawing 6...
ended drawing 6
如我们所见,我们甚至没有开始绘制 1、2 和 3,因为它们被新值替换得太快了。