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.
}
}
delay
在 suspendCancellableCoroutine
块中不起作用,因为它没有标记为 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
}
}
我想模拟文件加载,我想延迟代码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.
}
}
delay
在 suspendCancellableCoroutine
块中不起作用,因为它没有标记为 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
}
}