CoroutineScope(job+Dispatchers.Main) 运行 如何在 main/UI 线程上?
How can CoroutineScope(job+Dispatchers.Main) run on the main/UI thread?
如果 CoroutineScope(job+Dispatchers.Main){...}
运行 内的操作在主线程上那么它怎么不违反 Android 的慢速(阻塞)操作(网络等)的要求不允许在 main/UI 线程上 运行?我可以 运行 使用此范围阻止操作,并且 UI 根本不会冻结。
如果有人能解释幕后发生的事情,我将不胜感激。我的猜测是它类似于 JavaScript 如何使用事件循环管理阻塞操作,但我很难找到任何相关资料。
运行 阻塞操作和运行暂停操作CoroutineScope(Dispatchers.Main)
是两个不同的东西.
delay()
是一个挂起函数,它是非阻塞的
CoroutineScope(Dispatchers.Main){
delay(6000)
}
虽然Thread.sleep()
正在阻塞并且调用下面的代码会导致ANR
CoroutineScope(Dispatchers.Main){
Thread.sleep(6000)
}
我建议您查看 Roman Elizarov 在 Kotlinconf 2017 上关于 Kotlin 协程的演讲,尤其是他运行 100,000 的部分 delay()
My guess is that it is similar to how JavaScript manages blocking operations with the event loop
是的,这是正确的,事件循环对于协同程序的工作至关重要。基本上,当你这样写的时候:
uiScope.launch {
delay(1000)
println("A second has passed")
}
编译成和下面效果一样的代码:
Handler(Looper.mainLooper()).postDelayed(1000) { println("A second has passed") }
主要概念是 continuation,一个实现状态机的对象,该状态机对应于您在可挂起函数中编写的顺序代码。当您调用 delay
或任何其他可暂停函数时,延续的入口点方法 return 是一个特殊的 COROUTINE_SUSPENDED
值。稍后,当某些外部代码得出可挂起函数的 return 值时,它必须调用 continuation.resume(result)
。此调用将被负责的调度程序拦截,它将 post 此调用作为 GUI 事件循环中的一个事件。当事件处理程序出队并执行时,您将回到状态机内部,该状态机确定从哪里恢复执行。
您可以查看 this answer 以获得更充实的使用 Continuation
API 的示例。
如果 CoroutineScope(job+Dispatchers.Main){...}
运行 内的操作在主线程上那么它怎么不违反 Android 的慢速(阻塞)操作(网络等)的要求不允许在 main/UI 线程上 运行?我可以 运行 使用此范围阻止操作,并且 UI 根本不会冻结。
如果有人能解释幕后发生的事情,我将不胜感激。我的猜测是它类似于 JavaScript 如何使用事件循环管理阻塞操作,但我很难找到任何相关资料。
运行 阻塞操作和运行暂停操作CoroutineScope(Dispatchers.Main)
是两个不同的东西.
delay()
是一个挂起函数,它是非阻塞的
CoroutineScope(Dispatchers.Main){
delay(6000)
}
虽然Thread.sleep()
正在阻塞并且调用下面的代码会导致ANR
CoroutineScope(Dispatchers.Main){
Thread.sleep(6000)
}
我建议您查看 Roman Elizarov 在 Kotlinconf 2017 上关于 Kotlin 协程的演讲,尤其是他运行 100,000 的部分 delay()
My guess is that it is similar to how JavaScript manages blocking operations with the event loop
是的,这是正确的,事件循环对于协同程序的工作至关重要。基本上,当你这样写的时候:
uiScope.launch {
delay(1000)
println("A second has passed")
}
编译成和下面效果一样的代码:
Handler(Looper.mainLooper()).postDelayed(1000) { println("A second has passed") }
主要概念是 continuation,一个实现状态机的对象,该状态机对应于您在可挂起函数中编写的顺序代码。当您调用 delay
或任何其他可暂停函数时,延续的入口点方法 return 是一个特殊的 COROUTINE_SUSPENDED
值。稍后,当某些外部代码得出可挂起函数的 return 值时,它必须调用 continuation.resume(result)
。此调用将被负责的调度程序拦截,它将 post 此调用作为 GUI 事件循环中的一个事件。当事件处理程序出队并执行时,您将回到状态机内部,该状态机确定从哪里恢复执行。
您可以查看 this answer 以获得更充实的使用 Continuation
API 的示例。