问题
I'm trying to access chatting room Using firestore and coroutines.
fun getOwner() {
runBlocking {
var de = async(Dispatchers.IO) {
firestore.collection("Chat").document("cF7DrENgQ4noWjr3SxKX").get()
}
var result = de.await().result
}
But i get error like this :
E/AndroidRuntime: FATAL EXCEPTION: Timer-0
Process: com.example.map_fetchuser_trest, PID: 19329
java.lang.IllegalStateException: Task is not yet complete
at com.google.android.gms.common.internal.Preconditions.checkState(Unknown Source:29)
at com.google.android.gms.tasks.zzu.zzb(Unknown Source:121)
at com.google.android.gms.tasks.zzu.getResult(Unknown Source:12)
at com.example.map_fetchuser_trest.model.Repository$getOwner$1.invokeSuspend(Repository.kt:53)
How can i get chat document? when i use origin api like below, I can access chat room document.
firestore.collection("Chat").document(
"cF7DrENgQ4noWjr3SxKX"
).get().addOnCompleteListener { task ->
if (task.isSuccessful) {
val chatDTO = task.result?.toObject(Appointment::class.java)
}
}
回答1:
Task
is the thing one awaits on, but you wrapped it in another layer of async
. Remove the async
:
fun getOwner() {
runBlocking {
var de = firestore.collection("Chat").document("cF7DrENgQ4noWjr3SxKX").get()
var result = de.await().result
}
}
However, by using runBlocking()
you have shot yourself in the foot and wrote blocking code that just formally uses an async API to no good effect.
To truly benefit from it, you must have a
suspend fun getOwner() = firestore
.collection("Chat")
.document("cF7DrENgQ4noWjr3SxKX")
.get()
.await()
.result
and launch
a coroutine at the place you call it from:
launch {
val owner = getOwner()
// update the GUI
}
This assumes you're calling launch
from an object that is a CoroutineScope
.
回答2:
The usage of runBlocking{..}
in the first code snippet works as follows: the runBlocking
function blocks to execute the parameter lambda code (and the lambda code will suspend inside). It gives less sense.
You may want to start a coroutine with launch{..}
function instead and use withContext(Dispatchers.Main){..}
to have the block executed in the UI thread, e.g. to show the fetched results. You may also implement CoroutineScope
in your activity class.
The first step - you need to turn the Firebase API call into a suspending function. It could be done with suspendCoroutine{..}
function (there are several more functions like suspendCancellableCoroutine{..}
in the kotlinx.coroutines library.
There is an integration library with Google Play Services that provides support for Firebase
https://github.com/Kotlin/kotlinx.coroutines/tree/master/integration/kotlinx-coroutines-play-services
来源:https://stackoverflow.com/questions/55204428/how-to-use-kotlin-coroutines-in-firebase-database