He estado leyendo muchos artículos y viendo muchos videos sobre las co-rutinas de Kotlin últimamente y, a pesar de mis esfuerzos, todavía no puedo encontrarles sentido en mi cabeza.
Creo que finalmente encontré una manera de ilustrar mi problema:
class MyViewModel() : CoroutineScope { override val coroutineContext = Dispatchers.Main + Job() fun foo() = launch(handler) { Log.e("test", "A") } } class MainActivity : Activity() { override fun onCreate() { MainViewModel().foo() Log.e("test", "B") } }La salida de esto es:
E/test: B E/test: A Y no entiendo cómo puede ser este el caso, estoy usando solo un hilo (el hilo principal). Si mi código se ejecuta secuencialmente, cuando llegue a la línea log(B) ... log(A) ya debería estar impreso.
¿La biblioteca de rutinas utiliza otros subprocesos internamente para lograr esto? Esta es la única explicación que se me ocurrió, pero no he encontrado nada que lo diga en los documentos.
PD: Lo siento por incluir android en la mezcla, pero este código:
fun main() { GlobalScope.launch(Dispatchers.Unconfined) { // launch new coroutine in background and continue print(Thread.currentThread().name + "World!") // print after delay } (0 .. 1000).forEach { print(".") } } parece funcionar como se esperaba e imprime: main @coroutine#1World!...........................
porque 1 thread == sequential work
Espero que mi pregunta tenga sentido, ¡gracias por leer!
Debajo del capó, el despachador principal usa un controlador para publicar un Runnable en MessageQueue. Básicamente, se agregará al final de la cola de eventos. Esto significa que se ejecutará pronto, pero no inmediatamente. Por eso se imprime "B" antes que "A".
Puedes encontrar más información en este artículo .
EDITAR por OP (lea el artículo anterior antes de leer esto):
Solo quería aclarar por qué el ejemplo anterior de Android funcionaba bien, en caso de que alguien todavía se lo pregunte.
fun main() { GlobalScope.launch(Dispatchers.Unconfined) { // launch new coroutine in background and continue print(Thread.currentThread().name + "World!") // print after delay } (0 .. 1000).forEach { print(".") } } Estamos configurando GlobalScope para usar el despachador UNCONFINED , y este despachador tiene isDispatchNeeded establecido en false . false significa "programar en el hilo actual", y es por eso que vemos los registros imprimiéndose secuencialmente. UNCONFINED no debe usarse en código normal.
Todos los demás despachadores tienen isDispatchNeeded establecido en true , incluso el despachador de interfaz de usuario. consulte: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/is-dispatch-needed.html
(por cierto, GlobalScope usa el despachador Default si no especificamos uno)