我有一种从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中?
答案 0 :(得分:2)
如果你想确保lock.await()
不会让你当前的线程永远等待,你需要确保调用lock.countDown()
无论发生什么,所以你应该用{{1}围绕阻止侦听器的代码,以便在try/finally
块内调用lock.countDown()
。
实际上,如果例如finally
失败,则使用当前代码,将永远不会调用BitmapFactory.decodeByteArray(bytes, 0, bytes.size).scale(ctx.dip(64))
,这将使调用lock.countDown()
的线程永远等待。
例如,如果成功,听众的代码应该是:
lock.await()