[英]Why do these two methods shows different results?
我試圖使用協程 kotlin 從 Firestore 獲取 arraylist。 我寫了兩種不同的方法來獲得相同的結果。 這些是方法
方法A
fun methodA(type: String) {
CoroutineScope(IO).launch {
val myList = mutableListOf<Product>()
val job = async(IO) {
db.collection("Products").get().addOnSuccessListener { snapShot ->
snapShot.forEach { subSnapShot ->
if (subSnapShot.exists()) {
if (subSnapShot["name"]?.equals(type) == true) {
val category = type
val url = subSnapShot["url"].toString()
val type = subSnapShot["type"].toString()
val item = Product(url, category, subSnapShot.id, type)
myList.add(item)
}
}
}
}
myList
}.await()
temp.postValue(job)
}
}
方法B
fun methodB(type: String) {
CoroutineScope(IO).launch {
val myList = mutableListOf<Product>()
db.collection("Products").get().addOnSuccessListener { snapShot ->
snapShot.forEach { subSnapShot ->
if (subSnapShot.exists()) {
if (subSnapShot["name"]?.equals(type) == true) {
val category = type
val url = subSnapShot["url"].toString()
val type = subSnapShot["type"].toString()
val item = Product(url, category, subSnapShot.id, type)
myList.add(item)
}
}
}
}.await()
temp.postValue(myList)
}
}
我期望從這兩種方法中得到相同的結果,但是MethodA返回一個空列表,而MethodB返回項目列表。 如果我像MethodB那樣獲取這樣的列表,我該如何修復我的MethodA
這些都不會可靠地工作。 這是一個競爭條件,您很幸運使用了 MethodB。 它不會一直成功。
問題是即使您在任務上調用await()
,回調也不一定會在await()
返回之前運行。
一個監聽器被異步調用。 它下面的代碼繼續在添加它的同一線程中運行。 然后,當結果完成時,偵聽器內的代碼將在未來一段時間內運行(可能只有幾毫秒,但仍然在運行其他代碼之后)。
由於您使用的是協程,因此您應該使用await()
的返回值,而不是添加偵聽器。 您還需要使用try/catch
以防失敗。 然后你的代碼可以按照它出現的順序順序運行,利用協程的最佳特性之一。
在實踐中,您應該使用在適當時間取消的現有 CoroutineScope,而不是創建一次性 CoroutineScope 來啟動單個協程然后將其丟棄。 但我在這個例子中留下了這個,因為這不是你要問的。
以下是正確執行此操作的方法(CoroutineScope 部分除外):
fun methodC(type: String) {
CoroutineScope(IO).launch {
try {
db.collection("Products").get().await()
.filter { it.exists() && it["name"]?.equals(type) == true }
.map { subSnapShot ->
val category = type
val url = subSnapShot["url"].toString()
val type = subSnapShot["type"].toString()
Product(url, category, subSnapShot.id, type)
}
.let(temp::postValue)
} catch (e: Exception) {
Log.e(TAG, "Failed to query products.", e)
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.