从内部嵌套的协程返回标签Kotlin

时间:2020-07-09 00:24:00

标签: kotlin asynchronous kotlin-coroutines coroutinescope

用例:我想从主线程异步执行很多操作,但又希望彼此并行执行。

val scope = CoroutineScope(Dispatchers.IO)
val items = // List of items to do something.

scope.launch {
    items.forEach { item ->
        scope.launch {
            if (itemFailsValidation(item)) {
                // Here I want to skip this item but continue the forEach loop.
                return@launch // "There is more than one label with such a name in this" scope"
            }
            doSomethingThatMightTakeABit(item)
         }
     }
}

如果我尝试添加标签,例如inner@scope.launch,则编辑器会说“标签是多余的,因为在'break','continue'或'return'中都不能引用它'表情”

有人知道这样做的好方法吗?

2 个答案:

答案 0 :(得分:3)

如果需要从Lambda表达式返回,则必须label it and qualify the return。为了让您的案件从内部协程返回:

scope.launch {
    items.forEach { item ->
        scope.launch innerScope@ {
            if (itemFailsValidation(item)) {
                return@innerScope
            }
            doSomethingThatMightTakeABit(item)
        }
    }
}

但是我们可以简化您的案例并重写代码而无需使用标签:

scope.launch {
    items.forEach { item ->
        if (!itemFailsValidation(item)) {
            scope.launch { doSomethingThatMightTakeABit(item) }
        }
    }
}

// OR

items.forEach { item ->
    if (!itemFailsValidation(item)) {
        scope.launch { doSomethingThatMightTakeABit(item) }
    }
}    

如果您要等待所有协程完成并在UI线程上执行某些操作:

scope.launch(Dispatchers.Main) {
    processItemsInBackground()

    // update UI after processing is finished
}

suspend fun processItemsInBackground() = withContext(Dispatchers.IO) {
    // withContext waits for all children coroutines
    items.forEach { item ->
        if (!itemFailsValidation(item)) {
            launch { doSomethingThatMightTakeABit(item) }
        }
    }
}

答案 1 :(得分:1)

您可以使用name@关键字更改lambda的名称。

示例:

scope.launch outerCoroutine@ {
    items.forEach { item ->
        scope.launch {
            if (itemFailsValidation(item)) {
                return@outerCoroutine
            }
            doSomethingThatMightTakeABit(item)
         }
     }
}

此功能的文档不正确,但是This expressions之类的一些文档中有演示用法,而标准库中定义的某些函数正在使用它。

编辑:该文件实际上记录在Return and Jumps上。