Kotlin协程暂停和延迟

Kotlin coroutine suspend and delay

我想模拟文件加载,我想延迟代码4秒,我做不到。

 suspend fun showLoadingProgress() : String = suspendCancellableCoroutine{ continuation ->

    while (fileIsBeingLoaded())
    {
        delay(4000)

        val percent = ((loadedBites.toDouble() / fileBites.toDouble())*100).toInt()

        continuation.resume("$loadedBites/$fileBites ($percent%)")
    }
}

我有一个错误:暂停函数只能从协程体中调用。但是

当我有这样的代码时,如果没有 returning 字符串,那么我的延迟就可以工作了。为什么?:

   suspend fun showLoadingProgress() {

    while (fileIsBeingLoaded())
    {
        delay(4000)

        val percent = ((loadedBites.toDouble() / fileBites.toDouble())*100).toInt()

        continuation.resume("$loadedBites/$fileBites ($percent%)")
    }
}

如何使延迟和 return 成为一个字符串?

suspendCancellableCoroutine 主要与回调一起使用,以暂停协程执行直到回调触发,例如:

suspend fun getUser(id: String): User = suspendCancellableCoroutine { continuation ->
          Api.getUser(id) { user ->
              continuation.resume(user)
          }
          continuation.invokeOnCancellation {
              // clear some resources, cancel tasks, close streams etc.
          }
    }

delaysuspendCancellableCoroutine 块中不起作用,因为它没有标记为 suspend,因此我们不能在其中调用 suspend 函数。 suspendCancellableCoroutine 函数定义如下:

public suspend inline fun <T> suspendCancellableCoroutine(
    crossinline block: (CancellableContinuation<T>) -> Unit
): T = ...

如果它是这样定义的(请注意 block 标记为 suspend):

public suspend inline fun <T> suspendCancellableCoroutine(
    crossinline block: suspend (CancellableContinuation<T>) -> Unit
): T = ...

那么我们就可以调用里面的delay函数了


不知道为什么要用while循环,好像是多余的。或者你错误地使用它来加载进度。

你没有回调,所以你可以去掉 suspendCancellableCoroutine:

suspend fun getLoadingProgress(): String {
    delay(4000)
    val percent = ((loadedBites.toDouble() / fileBites.toDouble())*100).toInt()
    return "$loadedBites/$fileBites ($percent%)"
}

suspend fun showLoadingProgress() {
    while (fileIsBeingLoaded()) {
        val progress = getLoadingProgress()
        // use progress
    }
}

另一种方法是使用 Flow 发出加载进度。它看起来像下面使用 flow builder:

fun getLoadingProgress(): Flow<String> = flow {
    while (fileIsBeingLoaded()) {
        delay(4000)
        val percent = ((loadedBites.toDouble() / fileBites.toDouble())*100).toInt()
        emit("$loadedBites/$fileBites ($percent%)")
    }
}

并收集值:

someCoroutineScope.launch {
    getLoadingProgress().collect { progress ->
        // use progress
    }
}