Android kotlin中的多个异步等待
PromType中的obj=[字符串列表] 它更像是在这里运行的10个firebase查询,查找10个特定的节点集并进一步深入 我不确定的是,我是否需要在每个查询上启用async/await,但我只想运行其中10个查询,然后得出couponKey是否为空。我只想显示输入的优惠券是否正确 此外,在changeUserType(couponKey、couponFoundAtKey)中,会发生一些数据库写入操作Android kotlin中的多个异步等待,android,kotlin,async-await,coroutine,kotlin-coroutines,Android,Kotlin,Async Await,Coroutine,Kotlin Coroutines,PromType中的obj=[字符串列表] 它更像是在这里运行的10个firebase查询,查找10个特定的节点集并进一步深入 我不确定的是,我是否需要在每个查询上启用async/await,但我只想运行其中10个查询,然后得出couponKey是否为空。我只想显示输入的优惠券是否正确 此外,在changeUserType(couponKey、couponFoundAtKey)中,会发生一些数据库写入操作 fun checkPromo(promoCodeET: String) = async(U
fun checkPromo(promoCodeET: String) = async(UI) {
try {
val database = PersistentFirebaseUtil.getDatabase().reference
val job = async(CommonPool) {
for (obj in promoType) {
val query = database.child("promos").child(obj).orderByChild("promoCode").equalTo(promoCodeET)
query.addListenerForSingleValueEvent(object :
ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
if (dataSnapshot.exists()) {
couponKey = dataSnapshot.key.toString()
couponFoundAtKey = dataSnapshot.children.first().key.toString()
if (couponKey.isNotEmpty())
changeUserType(couponKey, couponFoundAtKey)
flag = true
}
}
override fun onCancelled(error: DatabaseError) {
// Failed to read value
}
})
if (flag) break
}
}
job.await()
}
catch (e: Exception) {
}
finally {
if (couponKey.isEmpty()){
Toast.makeText(this@Coupon, "Invalid coupon", Toast.LENGTH_LONG).show()
}
flag = true
}
}
我发现您的代码有几个地方有问题:
async(UI)
,这没有意义async(CommonPool)
也没有意义,因为您的数据库调用已经是异步的async
之后立即wait
,使其不是真正的“async”(但如上所述,无论是否使用它,整个过程都是异步的)suspend fun
,它的返回值是成对的(couponKey,优惠券)
:
您说changeUserType
执行一些数据库操作,所以我将它们包装在withContext(CommonPool)
中
还要注意的是,我在函数外部提取了promo类型上的循环。这将导致按顺序执行查询,但您只需编写不同的调用代码即可实现并行查找:
var numDone = 0
var found = false
promoType.forEach { type ->
launch(UI) {
fetchPromo(type, "promo-code-et")
.also { numDone++ }
?.also { (couponKey, coupon) ->
found = true
launch(CommonPool) {
changeUserType(couponKey, coupon)
}
}
?: if (numDone == promoType.size && !found) {
Toast.makeText(this@Coupon, "Invalid coupon", Toast.LENGTH_LONG).show()
}
}
}
在你的回答中,这就像天堂一样简单!关于launch(UI)和.takeIf在哪里可以阅读的更多信息,请参考我的意见。这些都是协作程序的重要资源:
。还有和。takeIf
是任何类型的扩展函数,包括null
。它们是标准库的一部分,也是习惯性Kotlin代码的一个基本方面。我建议您学习所有这些标准扩展函数,并尝试在任何地方使用它们,这样您就可以了解它们提供的价值。
launch(UI) {
var found = false
for (type in promoType) {
val (couponKey, coupon) = fetchPromo(type, "promo-code-et") ?: continue
found = true
withContext(CommonPool) {
changeUserType(couponKey, coupon)
}
break
}
if (!found) {
Toast.makeText(this@Coupon, "Invalid coupon", Toast.LENGTH_LONG).show()
}
}
var numDone = 0
var found = false
promoType.forEach { type ->
launch(UI) {
fetchPromo(type, "promo-code-et")
.also { numDone++ }
?.also { (couponKey, coupon) ->
found = true
launch(CommonPool) {
changeUserType(couponKey, coupon)
}
}
?: if (numDone == promoType.size && !found) {
Toast.makeText(this@Coupon, "Invalid coupon", Toast.LENGTH_LONG).show()
}
}
}