CountDownLatch не освобождает поток

У меня есть метод, который загружает изображение из Firebase Storage. Он вызван в фоновом потоке, и мне нужно заблокировать его, пока изображение не будет загружено (чтобы избежать обратного ад). Вот код (в Котлине)

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 (ignored: NullPointerException) { lock.countDown() } lock.await() return result } 

Но поток остается заблокированным навсегда

Logcat:

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

UPD: Может ли быть причиной, что код Firebase – это Java, а мой код – в Котлине?

Если вы хотите быть уверенным, что lock.await() не заставит ваш текущий поток ждать навсегда, вам нужно убедиться, что lock.countDown() вызывается тем, что происходит, поэтому здесь вы должны окружить с помощью try/finally блок кода ваших слушателей, чтобы вызвать lock.countDown() в блоке finally .

В противном случае с вашим текущим кодом, если, например, BitmapFactory.decodeByteArray(bytes, 0, bytes.size).scale(ctx.dip(64)) терпит неудачу, lock.countDown() никогда не будет вызван, который сделает lock.await() вызовов потоков lock.await() wait lock.await() ждать вечно.

Например, в случае успеха код вашего слушателя должен быть скорее:

 .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) }