Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android kotlin中的多个异步等待_Android_Kotlin_Async Await_Coroutine_Kotlin Coroutines - Fatal编程技术网

Android kotlin中的多个异步等待

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

PromType中的obj=[字符串列表] 它更像是在这里运行的10个firebase查询,查找10个特定的节点集并进一步深入

我不确定的是,我是否需要在每个查询上启用async/await,但我只想运行其中10个查询,然后得出couponKey是否为空。我只想显示输入的优惠券是否正确

此外,在changeUserType(couponKey、couponFoundAtKey)中,会发生一些数据库写入操作

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()
                }
        }
    }