Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

235
Visualizações
Coroutine launch() mientras está dentro de otra coroutine

Tengo el siguiente código (pseudocódigo)

 fun onMapReady() { //do some stuff on current thread (main thread) //get data from server GlobalScope.launch(Dispatchers.IO){ getDataFromServer { result-> //update UI on main thread launch(Dispatchers.Main){ updateUI(result) //BREAKPOINT HERE NEVER CALLED } } } }

Como se indica allí como comentario, el código nunca ingresa a la rutina y se envía a la cola principal. Sin embargo, lo siguiente funciona si uso explícitamente GlobalScope.launch(Dispatchers.Main) en lugar de simplemente launch(Dispatchers.Main)

 fun onMapReady() { //do some stuff on current thread (main thread) //get data from server GlobalScope.launch(Dispatchers.IO){ getDataFromServer { result-> //update UI on main thread GlobalScope.launch(Dispatchers.Main){ updateUI(result) //BREAKPOINT HERE IS CALLED } } } }

¿Por qué no funciona el primer enfoque?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Creo que el problema aquí es que getDataFromServer() es asíncrono, regresa inmediatamente y, por lo tanto, invoca launch(Dispatchers.Main) después de salir del GlobalScope.launch(Dispatchers.IO) { ... } . En otras palabras: intenta iniciar una corrutina utilizando un ámbito de corrutina que ya ha terminado.

Mi sugerencia es no mezclar API asincrónicas basadas en devolución de llamadas con rutinas como esta. Las rutinas funcionan mejor con funciones de suspensión que son síncronas. Además, si prefiere ejecutar todo de forma asíncrona e independiente de otras tareas (su onMapReady() inició 3 operaciones asíncronas separadas), entonces creo que las corrutinas no son una buena opción.

Hablando de su ejemplo: ¿está seguro de que no puede ejecutar getDataFromServer() directamente desde el hilo principal? No debería bloquear el hilo principal ya que es asíncrono. De manera similar, en algunas bibliotecas, las devoluciones de llamada se ejecutan automáticamente en el hilo principal y, en tal caso, su ejemplo podría reemplazarse simplemente con:

 fun onMapReady() { getDataFromServer { result-> updateUI(result) } }

Si el resultado se ejecuta en un subproceso en segundo plano, puede usar GlobalScope.launch(Dispatchers.Main) como lo hizo, pero esta no es realmente la forma habitual en que usamos las corrutinas. O puede usar utilidades como, por ejemplo , runOnUiThread() en Android, lo que probablemente tenga más sentido.

over 4 years ago · Santiago Trujillo Relatório

0

@broot ya explicó la esencia del problema. Está intentando launch una corrutina en el ámbito secundario del GlobalScope.launch externo, pero ese ámbito ya está listo cuando se llama a la devolución de llamada de getDataFromServer .

En resumen, no capture el alcance externo en una devolución de llamada que se llamará en un lugar/tiempo que no controla.

Una mejor manera de lidiar con su problema sería hacer que getDataFromServer suspenda en lugar de basarse en la devolución de llamada. Si es una API que no controla, puede crear un contenedor de suspensión de esta manera:

 suspend fun getDataFromServerSuspend(): ResultType = suspendCoroutine { cont -> getDataFromServer { result -> cont.resume(result) } }

A continuación, puede simplificar su código de llamada:

 fun onMapReady() { // instead of GlobalScope, please use viewModelScope or lifecycleScope, // or something more relevant (see explanation below) GlobalScope.launch(Dispatchers.IO) { val result = getDataFromServer() // you don't need a separate coroutine, just a context switch withContext(Dispatchers.Main) { updateUI(result) } } }

Como nota al margen, GlobalScope probablemente no sea lo que desea aquí. En su lugar, debe usar un alcance que se asigne al ciclo de vida de su vista o modelo de vista ( viewModelScope o lifecycleScope ) porque no está interesado en el resultado de esta rutina si la vista se destruye (por lo que debe cancelarse). Esto evitará fugas de corrutina si, por alguna razón, algo cuelga o gira dentro de la corrutina.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda