El uiThread de Anko no se dispara esporádicamente

Actualmente estoy usando doAsync de Anko para manejar tareas asíncronas. Específicamente, lo estoy usando para analizar una respuesta json a una ArrayList de objects de datos, como se ve a continuación:

// Asynchronously parse server response doAsync { val itemlist = parseResponse(response) uiThread { Otto.INSTANCE.post(UpdateRedeemedVoucherViewsEvent(itemlist)) } } 

La mayoría de las veces, como en un Google Pixel (Android 8.0.0) , esto funciona bien. Mis objects se analizan y el evento del bus de Otto se mostrará en el hilo de la interfaz de usuario.

Pero en algunos casos raros, este process falla. Hasta ahora noté que la llamada al hilo de la interfaz de usuario no se activará en un Galaxy S5 Mini (Android 5.1.1) . Aunque mis datos se analizaron sin errores ni excepciones, el fragment de código en los paréntesis de uiThread no se ejecutará.

Hasta el momento no he podido determinar ninguna razón para este comportamiento. No hay loggings de logcat, nada. No hay un esquema de cuándo aparecerá este error.

¿Alguien ha tenido el mismo o un problema similar con kotlin y / o Anko?

ACTUALIZACIÓN: he encontrado una solución por mí mismo, por favor vea mi respuesta a continuación para get una explicación.

Tuve el mismo problema, fue porque una exception no detectada está sucediendo en el background.

rodea tu tarea de background con un try / catch y deberías poder ver lo que está ocurriendo.

 doAsync { try { val itemlist = parseResponse(response) } catch(t: Throwable) { //TODO log your exception ] uiThread { Otto.INSTANCE.post(UpdateRedeemedVoucherViewsEvent(itemlist)) } } 

Gracias por su ayuda chicos. Lo he descubierto por mi count, así que estoy publicando esta respuesta por si acaso alguien más se enfrenta a este problema.

TL; DR: el context se pierde, por lo que el uiThread no se ejecutará

Solución: me encontré con esta publicación donde se mencionaba una característica importante del método uiThread :

Básicamente, usted tiene una function asíncrona que ejecutará su código en otro hilo y le dará la oportunidad de devolver el hilo principal usando uiThread. async es una function de extensión implementada para Context, y usará una reference débil de la misma, por lo que no impedirá que GC libere su memory.

Tras una investigación más exhaustiva, he encontrado el siguiente logging justo después de que se haya realizado mi análisis sintáctico y dónde debería haberse llamado el uiThread :

 I/art: Background partial concurrent mark sweep GC freed 30879(16MB) AllocSpace objects, 16(2MB) LOS objects, 40% free, 16MB/27MB, paused 2.123ms total 196.372ms 

Entonces, parece que efectivamente hay alguna acción de GC, que puede o no liberarse del context .

Para evitar esto, estoy usando Ankos runOnUiThread , que se puede invocar en una reference de context dada:

 // Asynchronously parse server response doAsync { val itemlist = parseResponse(response) context.runOnUiThread { Otto.INSTANCE.post(UpdateRedeemedVoucherViewsEvent(itemlist)) } } 

Por lo que puedo decir hasta ahora, esto parece haber hecho el truco.

  • Android - Kotlin: valor de retorno en la diversión asíncrona
  • Kotlin inesperado 'reference no resuelta'
  • Cómo llamar al constructor String de Java (char , int offset, int length) de Kotlin?
  • Comprender los ejecutores kotlin
  • ¿Cómo hacer que una class de datos en Kotlin sea inmutable con el object Date de Java en ella?
  • Vertx plus Koutlin coroutines cuelga para siempre
  • Entrada de console de lectura en Kotlin
  • Es posible get nombres de variables locales programáticamente en Java o Kotlin?
  • Herencia explícita de Any in Kotlin - ¿Puede y cómo se hace?
  • Cómo verificar el vacío lambda en kotlin
  • Criterio multicriterio de Kotlin no comstackndo