CountDownLatch no libera el hilo

Tengo un método que carga la image de Firebase Storage. Se llama en el hilo de background, y necesito bloquearlo, hasta que se cargue la image (para evitar el infierno de callback). Aquí está el código (en Kotlin)

override fun fromNet(): Bitmap? { Log.wtf(TAG, "$name loading from firebase") var result: Bitmap? = null val lock = CountDownLatch(1) try { FirebaseStorage.getInstance().getReferenceFromUrl(FIRE_STORAGE).child(ctx.getKGL().famkey) .child(name).getBytes(524288L) .addOnFailureListener { Log.wtf(TAG, "$name load failure") lock.countDown() } .addOnSuccessListener { bytes -> Log.wtf(TAG, "$name loaded") val b = BitmapFactory.decodeByteArray(bytes, 0, bytes.size).scale(ctx.dip(64)) result = b lock.countDown() ctx.saveToCache(name, b) } .addOnCompleteListener { Log.wtf(TAG, "on complete") lock.countDown() } } catch (ignonetworking: NullPointerException) { lock.countDown() } lock.await() return result } 

Pero el hilo permanece bloqueado para siempre

Logcat:

 A/MemberPhoto: xvd6z67gZfMCLG4c9mkGXKe9ML53 load failure A/MemberPhoto: on complete 

UPD: ¿Puede ser la causa, que el código de Firebase es Java y mi código está en Kotlin?

Si quieres estar seguro de que lock.await() no hará que el hilo actual espere por siempre, debes asegurarte de que lock.countDown() se llame pase lo que pase, así que aquí deberías rodear con un bloque try/finally el código de sus oyentes para llamar a lock.countDown() dentro de un bloque finally .

De hecho, con su código actual si, por ejemplo, BitmapFactory.decodeByteArray(bytes, 0, bytes.size).scale(ctx.dip(64)) falla, no se lock.countDown() lo que hará que el lock.await() llamada al hilo lock.await() espera para siempre

Por ejemplo, en caso de éxito, el código del oyente debería ser:

 .addOnSuccessListener { bytes -> try { Log.wtf(TAG, "$name loaded") val b = BitmapFactory.decodeByteArray(bytes, 0, bytes.size).scale(ctx.dip(64)) result = b } finally { lock.countDown() } ctx.saveToCache(name, b) } 
  • Propiedad diferida de Kotlin dependiendo de otra propiedad inicializada en init
  • No se puede crear un oyente de events de datos de spring en Kotlin
  • Cómo usar el calificador 2 @Named de Dagger en Kotlin
  • Desarrollo de biblioteca. Usando datos de fonts externas
  • Extendiendo la class genérica en Kotlin
  • Fragmento: Cambiar la visibilidad en la function
  • Inferir solo algunos parameters de tipo en Kotlin
  • Extensiones en Kotlin
  • Declaración "Cuando" statement vs Java "cambiar"
  • kotlin int boxed identity
  • Cómo agregar múltiples datos históricos a GoogleFit