CountDownLatch没有释放线程
我有一个方法,从Firebase存储加载图像。 它被称为后台线程,我需要阻止它,直到图像加载(以避免回调地狱)。 这里是代码(在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 (ignored: NullPointerException) { lock.countDown() } lock.await() return result }
但线程永远阻止
logcat的:
A/MemberPhoto: xvd6z67gZfMCLG4c9mkGXKe9ML53 load failure A/MemberPhoto: on complete
UPD:可能原因是,Firebase代码是Java,而我的代码是在Kotlin?
如果你想确保lock.await()
不会使你当前的线程永远等待,你需要确保lock.countDown()
被调用,无论发生什么事情,所以在这里你应该围绕一个try/finally
块的代码你的监听器为了在finally
块中调用lock.countDown()
。
除此之外,如果您的当前代码例如BitmapFactory.decodeByteArray(bytes, 0, bytes.size).scale(ctx.dip(64))
失败, lock.countDown()
永远不会被调用,这将使线程调用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) }