如果在CoroutineScope(job+Dispatchers.Main){...}
内部的操作在主线程上运行,那么为什么它不违反Android的要求,即不允许在主/UI线程上运行缓慢(阻塞)的操作(如网络等)?我可以使用此作用域运行阻塞操作,而UI根本不会冻结。
如果有人能解释一下底层发生了什么,我将不胜感激。 我猜这类似于JavaScript如何通过事件循环管理阻塞操作,但我难以找到任何相关材料。
如果在CoroutineScope(job+Dispatchers.Main){...}
内部的操作在主线程上运行,那么为什么它不违反Android的要求,即不允许在主/UI线程上运行缓慢(阻塞)的操作(如网络等)?我可以使用此作用域运行阻塞操作,而UI根本不会冻结。
如果有人能解释一下底层发生了什么,我将不胜感激。 我猜这类似于JavaScript如何通过事件循环管理阻塞操作,但我难以找到任何相关材料。
执行 阻塞 操作和执行 挂起 操作对于 CoroutineScope(Dispatchers.Main)
来说是两个不同的事情。
delay()
是一个挂起函数,它是非阻塞的。
CoroutineScope(Dispatchers.Main){
delay(6000)
}
Thread.sleep()
是阻塞的,调用下面的代码会导致 ANR
CoroutineScope(Dispatchers.Main){
Thread.sleep(6000)
}
我建议你查看罗曼·埃利扎罗夫在Kotlinconf 2017上关于Kotlin协程的演讲,特别是他运行100,000个delay()
的部分。
我猜想它与JavaScript如何使用事件循环处理阻塞操作类似。
是的,这是正确的,事件循环对于使协程工作非常重要。基本上,当你编写如下代码时:
uiScope.launch {
delay(1000)
println("A second has passed")
}
它被编译成与以下代码具有相同效果的代码:
Handler(Looper.mainLooper()).postDelayed(1000) { println("A second has passed") }
delay
函数是非阻塞的。OP正在询问一个阻塞操作,例如一些图像处理逻辑。 - alekop
delay(1000)
来暂停线程。如果我在UI线程上这样做,这不应该会导致ANR屏幕出现吗?@DmitriiLeonov - 372