Estoy tratando de acceder a la sala de chat usando firestore y coroutines.
fun getOwner() { runBlocking { var de = async(Dispatchers.IO) { firestore.collection("Chat").document("cF7DrENgQ4noWjr3SxKX").get() } var result = de.await().result }Pero me sale un error como este:
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)¿Cómo puedo obtener el documento de chat? cuando uso la API de origen como se muestra a continuación, puedo acceder al documento de la sala de chat.
firestore.collection("Chat").document( "cF7DrENgQ4noWjr3SxKX" ).get().addOnCompleteListener { task -> if (task.isSuccessful) { val chatDTO = task.result?.toObject(Appointment::class.java) } }Task es lo que uno espera, pero lo envolvió en otra capa de async . Eliminar el async :
fun getOwner() { runBlocking { var de = firestore.collection("Chat").document("cF7DrENgQ4noWjr3SxKX").get() var result = de.await().result } } Sin embargo, al usar runBlocking() , se disparó en el pie y escribió un código de bloqueo que solo usa formalmente una API asíncrona sin ningún efecto positivo.
Para beneficiarse realmente de él, debe tener un
suspend fun getOwner() = firestore .collection("Chat") .document("cF7DrENgQ4noWjr3SxKX") .get() .await() .result y launch una corrutina en el lugar desde el que la llamas:
launch { val owner = getOwner() // update the GUI } Esto supone que está llamando al launch desde un objeto que es un CoroutineScope .
val db = FirebaseFirestore.getInstance() override suspend fun saveBinToDB(bin: Bin): Result<Unit> { lateinit var result:Result<Unit> db.collection("bins") .add(bin) .addOnSuccessListener { documentReference -> Log.d(TAG, "DocumentSnapshot written with ID: ${documentReference.id}") result = Result.Success(Unit) } .addOnFailureListener { e -> Log.w(TAG, "Error adding document", e) result = Result.Error(Exception()) } .await() return result } implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.3.7"El uso de runBlocking{..} en el primer fragmento de código funciona de la siguiente manera: la función runBlocking se bloquea para ejecutar el código lambda del parámetro (y el código lambda se suspenderá en el interior). Da menos sentido.
Es posible que desee iniciar una corrutina con la función de launch{..} en su lugar y usar withContext(Dispatchers.Main){..} para que el bloque se ejecute en el subproceso de la interfaz de usuario, por ejemplo, para mostrar los resultados obtenidos. También puede implementar CoroutineScope en su clase de actividad.
El primer paso: debe convertir la llamada a la API de Firebase en una función de suspensión. Se podría hacer con suspendCoroutine{..} (hay varias funciones más como suspendCancellableCoroutine{..} en la biblioteca kotlinx.coroutines.
Hay una biblioteca de integración con Google Play Services que brinda soporte para Firebase
https://github.com/Kotlin/kotlinx.coroutines/tree/master/integration/kotlinx-coroutines-play-services