【问题标题】:Why flow doesn't execute, no error thrown?为什么流程不执行,没有抛出错误?
【发布时间】:2020-06-04 21:31:57
【问题描述】:

GlobalScope 或自定义 CoroutineScope 实例都不起作用:

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun makeFlow() = flow {
    println("sending first value")
    emit(1)
    println("first value collected, sending another value")
    emit(2)
    println("second value collected, sending a third value")
    emit(3)
    println("done")
}

@InternalCoroutinesApi
fun main() {
    val someScope = CoroutineScope(Dispatchers.Default)
    someScope.launch {
        makeFlow().collect { value ->
            println("value is $value")
        }
    }
    GlobalScope.launch {
        makeFlow().collect { value ->
            println("value is $value")
        }
    }
}

绝对没有输出或错误抛出

为什么?

更奇怪的是,当我添加 runBlocking{} 块时,一切都会执行:

val someScope = CoroutineScope(Dispatchers.Default)
    someScope.launch {
        makeFlow().collect { value ->
            println("someScope: value is $value")
        }
    }
    GlobalScope.launch {
        makeFlow().collect { value ->
            println("GlobalScope: value is $value")
        }
    }
    runBlocking {
        makeFlow().collect { value ->
            println("runBlocking: value is $value")
        }
    }

输出:

sending first value
sending first value
sending first value
runBlocking: value is 1
GlobalScope: value is 1
first value collected, sending another value
GlobalScope: value is 2
second value collected, sending a third value
GlobalScope: value is 3
done
someScope: value is 1
first value collected, sending another value
someScope: value is 2
second value collected, sending a third value
someScope: value is 3
done
first value collected, sending another value
runBlocking: value is 2
second value collected, sending a third value
runBlocking: value is 3
done

【问题讨论】:

    标签: kotlin kotlin-flow kotlin-coroutines


    【解决方案1】:

    您启动的协程没有完成,因为main 函数在触发它们后立即返回而无需等待它们,从而完成您的应用程序。没有发生错误,因为这是预期的行为。

    runBlocking 的 lambda 将不会返回,直到其中的所有协程都返回。在这种情况下,它恰好浪费了足够的时间让其他两个协程有时间完成,可能是因为它是最后启动的,并且做的工作量大致相同。

    如果你在前两个中引入延迟,他们将没有机会完成:

    fun main() {
        val someScope = CoroutineScope(Dispatchers.Default)
        someScope.launch {
            delay(100L)
            makeFlow().collect {
                makeFlow().collect { value ->
                    println("value is $value")
                }
            }
        }
        GlobalScope.launch {
            delay(100L)
            makeFlow().collect { value ->
                println("value is $value")
            }
        }
        runBlocking {
            makeFlow().collect { value ->
                println("runBlocking: value is $value")
            }
        }
    }
    
    sending first value
    runBlocking: value is 1
    first value collected, sending another value
    runBlocking: value is 2
    second value collected, sending a third value
    runBlocking: value is 3
    done
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-16
      • 2015-02-25
      • 2021-11-20
      • 2020-11-14
      • 1970-01-01
      • 1970-01-01
      • 2020-03-27
      • 1970-01-01
      相关资源
      最近更新 更多