要增加实时数据库中的数量,我只需使用:
override fun incrementQuantity() = flow {
try {
heroIdRef.update("quantity", FieldValue.increment(1)).await()
emit(Result.Success(true))
} catch (e: Exception) {
emit(Result.Failure(e))
}
}而且效果很好。当我需要先检查quantity,然后检查增量时,问题就出现了。上面的解决方案没有帮助,所以我需要使用事务。以下是我尝试过的:
override fun incrementQuantity() {
val transaction = object : Transaction.Handler {
override fun doTransaction(mutableData: MutableData): Transaction.Result {
val quantity = mutableData.getValue(Long::class.java) ?: return Transaction.success(mutableData)
if (quantity == 1L) {
mutableData.value = null
} else {
mutableData.value = quantity + 1
}
return Transaction.success(mutableData)
}
override fun onComplete(error: DatabaseError?, committed: Boolean, data: DataSnapshot?) {
throw error.toException()
}
}
heroIdRef.runTransaction(transaction)
}但我看不出Kotlin Coroutines是怎么用的。我只想调用await()并返回一个流,如第一个示例所示。我怎么能这么做?
发布于 2022-09-15 19:09:57
在这两种情况下,这实际上都不是流的正确使用,因为流用于检索多个串联的事物,但这只返回一件事。它更适合于直接返回该东西的挂起函数。
无论如何,我不是Firebase用户,所以我在这里可能犯了一个错误。看起来他们的Kotlin库没有提供运行事务的挂起函数版本。你可以这样写你自己的作品。这有点混乱,因为完成回调有三个参数,所以我们必须返回一个元组或一个包装类。
data class CompletedTransaction(val error: DatabaseError?, val committed: Boolean, val data: DataSnapshot?)
suspend fun DatabaseReference.runTransaction(
fireLocalEvents: Boolean = true,
action: (MutableData)->Transaction.Result
): CompletedTransaction = suspendCoroutine { continuation ->
val handler = object : Transaction.Handler {
override fun doTransaction(mutableData: MutableData): Transaction.Result =
action(mutableData)
override fun onComplete(error: DatabaseError?, committed: Boolean, data: DataSnapshot?) =
continuation.resume(CompletedTransaction(error, committed, data))
}
runTransaction(handler, fireLocalEvents)
}然后你就可以:
override suspend fun incrementQuantity(): Result {
val transaction = heroIdRef.runTransaction { mutableData ->
val quantity = mutableData.getValue(Long::class.java) ?: return@runTransaction Transaction.success(mutableData)
mutableData.value = if (quantity == 1L) null else quantity + 1
Transaction.success(mutableData)
}
val failure = transaction.error?.toException()?.let { Result.Failure(it) }
return failure ?: Result.Success(true)
}如果由于某种原因需要使用流,则如下所示:
override suspend fun incrementQuantity() = flow {
val transaction = heroIdRef.runTransaction { mutableData ->
val quantity = mutableData.getValue(Long::class.java) ?: return@runTransaction Transaction.success(mutableData)
mutableData.value = if (quantity == 1L) null else quantity + 1
Transaction.success(mutableData)
}
val failure = transaction.error?.toException()?.let { Result.Failure(it) }
emit(failure ?: Result.Success(true))
}https://stackoverflow.com/questions/73719810
复制相似问题