我想给你一个关于延续概念的简单例子。这就是挂起函数的作用,它可以冻结/挂起,然后继续/恢复。不要再从线程和信号量的角度考虑协程了。从延续甚至回调挂钩的角度来考虑它。
需要明确的是,可以使用suspend 函数暂停协程。让我们调查一下:
在 android 中我们可以这样做:
var TAG = "myTAG:"
fun myMethod() { // function A in image
viewModelScope.launch(Dispatchers.Default) {
for (i in 10..15) {
if (i == 10) { //on first iteration, we will completely FREEZE this coroutine (just for loop here gets 'suspended`)
println("$TAG im a tired coroutine - let someone else print the numbers async. i'll suspend until your done")
freezePleaseIAmDoingHeavyWork()
} else
println("$TAG $i")
}
}
//this area is not suspended, you can continue doing work
}
suspend fun freezePleaseIAmDoingHeavyWork() { // function B in image
withContext(Dispatchers.Default) {
async {
//pretend this is a big network call
for (i in 1..10) {
println("$TAG $i")
delay(1_000)//delay pauses coroutine, NOT the thread. use Thread.sleep if you want to pause a thread.
}
println("$TAG phwww finished printing those numbers async now im tired, thank you for freezing, you may resume")
}
}
}
上面的代码打印以下内容:
I: myTAG: my coroutine is frozen but i can carry on to do other things
I: myTAG: im a tired coroutine - let someone else print the numbers async. i'll suspend until your done
I: myTAG: 1
I: myTAG: 2
I: myTAG: 3
I: myTAG: 4
I: myTAG: 5
I: myTAG: 6
I: myTAG: 7
I: myTAG: 8
I: myTAG: 9
I: myTAG: 10
I: myTAG: phwww finished printing those numbers async now im tired, thank you for freezing, you may resume
I: myTAG: 11
I: myTAG: 12
I: myTAG: 13
I: myTAG: 14
I: myTAG: 15
想象一下它是这样工作的:
所以你启动的当前函数不会停止,只是一个协程会在它继续时暂停。线程不会通过运行挂起函数来暂停。
我认为this site can help 你直截了当,是我的参考。
让我们做一些很酷的事情并在迭代中间冻结我们的挂起函数。我们稍后会在onResume恢复它
存储一个名为 continuation 的变量,我们将为我们加载协程延续对象:
var continuation: CancellableContinuation<String>? = null
suspend fun freezeHere() = suspendCancellableCoroutine<String> {
continuation = it
}
fun unFreeze() {
continuation?.resume("im resuming") {}
}
现在,让我们回到挂起的函数,让它在迭代过程中冻结:
suspend fun freezePleaseIAmDoingHeavyWork() {
withContext(Dispatchers.Default) {
async {
//pretend this is a big network call
for (i in 1..10) {
println("$TAG $i")
delay(1_000)
if(i == 3)
freezeHere() //dead pause, do not go any further
}
}
}
}
然后在 onResume 中的其他地方(例如):
override fun onResume() {
super.onResume()
unFreeze()
}
然后循环将继续。知道我们可以在任何时候冻结挂起函数并在经过一段时间后恢复它,这非常好。也可以关注channels