难道 Flow.collect() 会阻塞 UI?

Sim*_*pps 1 android kotlin kotlin-coroutines kotlin-flow

我正在 kotlinlang.org 上阅读有关流程的文章:https ://kotlinlang.org/docs/flow.html

他们展示了下一个例子:

fun simple(): Flow<Int> = flow { 
   println("Flow started")
   for (i in 1..3) {
       delay(100)
       emit(I)
   }
}

fun main() = runBlocking<Unit> {
   println("Calling simple function...")
   val flow = simple()
   println("Calling collect...")
   flow.collect { value -> println(value) } 
   println("Calling collect again...")
   flow.collect { value -> println(value) } 
}
Run Code Online (Sandbox Code Playgroud)

他们说输出是:

Calling simple function...

Calling collect...
Flow started

1

2

3

Calling collect again...

Flow started

1

2

3
Run Code Online (Sandbox Code Playgroud)

因此,UI 线程似乎正在等待第一个flow.collect函数完成,然后再继续打印“再次调用收集...”

我希望当第一个流程构建器运行时,系统将打印“再次调用收集...”,因此输出将是:

Calling simple function...

Calling collect...

Calling collect again...

Flow started

1

2

3

Flow started

1

2

3
Run Code Online (Sandbox Code Playgroud)

我缺少什么?

Ten*_*r04 6

collect是一个suspend函数。挂起函数在调用代码中是同步的,因此就代码执行顺序而言,与调用 Listcollect没有什么不同。forEach

它不会阻塞调用线程,但它正在挂起,这意味着协程中的代码会等待它返回然后再继续。这是协程的主要功能——您可以同步调用耗时的代码而不阻塞线程。在幕后,挂起函数正在异步执行某些操作,但对于调用它的协程来说,它被视为同步。

在幕后,协程调度程序将协程分解为块,并将其传递给调用线程来运行。在这些块之间,即挂起的地方,调用线程可以自由地执行其他操作,因此不会被阻塞。

我在这里的回答可能有助于进一步解释这个概念。