我想要实现什么?
我有一个下载图像的任务,但随着屏幕滚动,它将取消以前的下载并开始下载新的下载。我希望当它取消
coroutine
下载上一张图像时,它会立即停止并释放 bandwidth
,以便新图像下载得更快。
我尝试了什么?
我尝试了多种方法来停止
coroutine
,但即使在取消coroutine
之后,它仍然会继续下去,直到完成下载。当我取消 coroutine
时,它会将变量 isActive
变为 false
并停止调用进一步的挂起函数。但问题是,如果运行 loop
1000000
次或从 network
下载图像,则此任务将不会取消,除非完成。 Like 循环将完成它的 1000000
迭代,然后协程将被取消。
我已经尝试过这些但没有成功:
job.cancel()
scope.cancel()
我尝试了很多方法来实现这一目标,但没有解决。我现在无法在我的项目中使用任何库。
这个用例不是通过线程、执行器服务、协程来实现的。因为所有人的行为都一样。
更多类似问题:
Kotlin 协程必须配合才能允许取消。这意味着它有一些检查点调用一个挂起函数。这是有道理的,因为有些过程是原子的,不应该在中间停止。
无法取消的不良协程的一个示例:
var job = launch {
var time = System.currentTimeMillis()
var i = 0
while (i < 1000) {
if (System.currentTimeMillis() >= time) {
println("Loop number ${++i} ")
time += 500
}
}
}
为了使其可取消,您可以在每次迭代开始时添加yield()。以下是可取消的协程:
coroutineScope {
var job = launch {
var time = System.currentTimeMillis()
var i = 0
while (i<1000) {
yield()
if (System.currentTimeMillis() >= time) {
println("Loop number ${++i}")
time += 500
}
}
}
// wait some time
delay(1300)
println("Stopping the coroutine....")
job.cancel()
job.join()
// or call job.cancelAndJoin()
}
协程取消是合作性的。协程代码必须 配合可取消。所有暂停功能 kotlinx.coroutines 是可以取消的。他们检查取消 协程并在取消时抛出 CancellationException。然而,如果 协程正在计算中,并且不检查 取消,则无法取消,如下例 显示:
val startTime = System.currentTimeMillis()
val job = launch(Dispatchers.Default) {
var nextPrintTime = startTime
var i = 0
while (i < 5) { // computation loop, just wastes CPU
// print a message twice a second
if (System.currentTimeMillis() >= nextPrintTime) {
println("job: I'm sleeping ${i++} ...")
nextPrintTime += 500L
}
}
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.")
运行它以查看即使在取消后它也会继续打印“我正在睡觉”,直到作业在五次迭代后自行完成
使计算代码可取消
就像下面的例子所示:
val startTime = System.currentTimeMillis()
val job = launch(Dispatchers.Default) {
var nextPrintTime = startTime
var i = 0
while (isActive) { // cancellable computation loop
// print a message twice a second
if (System.currentTimeMillis() >= nextPrintTime) {
println("job: I'm sleeping ${i++} ...")
nextPrintTime += 500L
}
}
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.")
参考官方文档这里
尝试取消上下文:
this.coroutineContext.cancel()
我尝试拨打
job.cancel()
,但没成功。但是当我打电话给job.cancel(null)
时。它取消当前正在运行的作业。您可以在 null
的参数中传递 CancellationException
或 cancel(cause:CancellationException? = null)
。
我不知道它发生的真正原因,但它与
job.cancel(null)
一起工作。尽管如此,在这两种方式下,我们都在底层调用相同的函数。