如何使用 Kotlin 协程 运行 Firebase 事务?

How to run a Firebase Transaction using Kotlin Coroutines?

我正在尝试 运行 在 Kotlin 的暂停功能下进行 Firebase 事务,但我没有看到相关文档。

我正在使用

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.5.2'

for coroutines with firebase(例如:setValue(*).await() )但是 运行 似乎没有 await 函数交易(*)

override suspend fun modifyProductStock(
    product: ProductModel,
    valueToModify: Long,
    replace: Boolean
) {
    CoroutineScope(Dispatchers.Main).launch {
        val restaurantId = authRepository.restaurantId.value ?: throw Exception("No restaurant!")

        val productId = product.id ?: throw Exception("No Product ID!")

        val reference = FirebaseDatabase.getInstance().getReference("database/$restaurantId").child("products")

        if (replace) {
            reference.child(productId).child("stock").setValue(valueToModify).await()
        } else {
            reference.child(productId).child("stock")
                .runTransaction(object : Transaction.Handler {

                    override fun doTransaction(p0: MutableData): Transaction.Result {
                        //any operation
                        return Transaction.success(p0)
                    }

                    override fun onComplete(p0: DatabaseError?, p1: Boolean, p2: DataSnapshot?) {
                    }

                })
        }
    }
}

鉴于 Kotlin example in the Firebase documentation on transactions 使用与您相同的回调样式,似乎确实没有对协同例程的具体支持。

可能值得在 Android SDK repo 上发布问题以添加它,或者听听为什么没有添加它。

您可以将其包装在 suspendCoroutine:

val result: DataSnapshot? = suspendCoroutine { c ->
    reference.child(productId).child("stock")
        .runTransaction(object : Transaction.Handler {
            override fun doTransaction(p0: MutableData): Transaction.Result {
                //any operation
                return Transaction.success(p0)
            }
    
            override fun onComplete(error: DatabaseError?, p1: Boolean, snapshot: DataSnapshot?) {
                c.resume(snapshot)
            }
        })
}

suspendCoroutine

Obtains the current continuation instance inside suspend functions and suspends the currently running coroutine.
In this function both Continuation.resume and Continuation.resumeWithException can be used either synchronously in the same stack-frame where the suspension function is run or asynchronously later in the same thread or from a different thread of execution.