我有一個包含我的 Firebase 實時資料庫鍵的地圖,并且想要檢索相應的鍵資料并將其放入結果資料串列中。如何按順序執行回圈?基本上,阻塞 Firebase 監聽器直到它得到結果,然后才迭代到回圈中的下一個鍵。
fun functionA() {
val resultFileDataList = List<DataSnapshot>()
for ((key, value) in filesMap) {
val dbRef = database.child("files").child(key)
dbRef.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {}
override fun onDataChange(dataSnapshot: DataSnapshot) {
resultFileDataList.add(dataSnapshot)
}
})
}
callFunctionB() // call this function only after all the data in the loop above is retrieved
}
我試過runBlocking {}但沒有運氣。
uj5u.com熱心網友回復:
您可以通過使用 Task 以這種方式實作它。Tasks.whenall()將等到所有任務完成。
fun functionA() {
val taskList = mutableListOf<Task<DataSnapshot>>()
val resultFileDataList = List<DataSnapshot>()
for ((key, value) in filesMap) {
val databaseReferenceTask: Task<DataSnapshot> = database.child("files").child(key).get()
taskList.add(databaseReferenceTask)
val resultTask = Tasks.whenAll(taskList)
resultTask.addOnCompleteListener {
for (task in taskList) {
val snapshotKey: String? = task.result.key
val snapShotValue = task.result
}
callFunctionB()
}
}
}
uj5u.com熱心網友回復:
由于您使用的是 Kotlin,因此最簡單的解決方案是使用Kotlin Coroutines。這樣,您可以使用掛起函式并為每個讀取操作呼叫等待。為此,請查看以下文章:
- 如何使用 get() 從 Firebase 實時資料庫中讀取資料?
但是,如果您需要通過其現有連接對請求進行管道傳輸,那么您應該考慮使用kotlinx-coroutines-play-services,在這種情況下您可以使用awaitAll()函式。
uj5u.com熱心網友回復:
這是一種方法:
suspend fun functionA() = suspendCoroutine<List<DataSnapshot>>{ continuation ->
val resultFileDataList = mutableListOf<DataSnapshot>()
for ((key, value) in filesMap) {
val dbRef = database.child("files").child(key)
dbRef.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {}
override fun onDataChange(dataSnapshot: DataSnapshot) {
resultFileDataList.add(dataSnapshot)
if(resultFileDataList.size == fileMaps.size){
continuation.resume(resultFileDataList)
}
}
})
}
}
然后你可以像這樣在任何你想要的地方呼叫函式:
CoroutineScope(Dispatchers.IO).launch {
val dataSnapshotList = functionA()
functionB(dataSnapshotList)
}
請記住,最好使用以下內容將協程系結到活動的生命周期:
lifecycleScope.launch(Dispatchers.IO) {
val dataSnapshotList = functionA()
functionB(dataSnapshotList)
}
筆記:
這將基本上等待所有資料發生變化,以便onDataChanged()觸發,當添加最后一個檔案時,繼續協程并回傳值。根據用戶的行為,這可能需要很長時間才能完成,因為即使其中一個檔案沒有更改,協程也不會恢復。
此外,如果onCancelled()為一個檔案觸發,這將永遠不會完成。因此,如果您絕對確定onDataChanged()所有檔案都會觸發它,請使用它。否則,實作某種超時功能以恢復不完整的資料。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/428771.html
標籤:安卓 火力基地 科特林 firebase-实时数据库 谷歌云平台
上一篇:失敗的Firebase身份驗證登錄嘗試次數過多會受到懲罰嗎?
下一篇:從RESTAPI插入一個物件
