CountDownLatch没有释放线程

时间:2016-10-28 16:55:40

标签: java android concurrency kotlin

我有一种从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中?

1 个答案:

答案 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()