如何在 firebase 数据库中使用 kotlin 协程

How to use kotlin coroutines in firebase database

我正在尝试使用 firestore 和协程访问聊天室。

    fun getOwner() {
        runBlocking {
            var de = async(Dispatchers.IO) {
                firestore.collection("Chat").document("cF7DrENgQ4noWjr3SxKX").get()
            }
            var result = de.await().result
        }

但是我得到这样的错误:

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.invokeSuspend(Repository.kt:53)

如何获取聊天文档?当我像下面这样使用 origin api 时,我可以访问聊天室文档。

        firestore.collection("Chat").document(
            "cF7DrENgQ4noWjr3SxKX"
        ).get().addOnCompleteListener { task ->
            if (task.isSuccessful) {
                val chatDTO = task.result?.toObject(Appointment::class.java)
            }
        }

Task 是等待的东西,但您将它包裹在另一层 async 中。删除 async:

fun getOwner() {
    runBlocking {
        var de =  firestore.collection("Chat").document("cF7DrENgQ4noWjr3SxKX").get()
        var result = de.await().result
    }
}

但是,通过使用 runBlocking(),您搬起石头砸自己的脚,编写了只是正式使用异步 API 的阻塞代码,但效果不佳。

要真正从中受益,您必须

suspend fun getOwner() = firestore
     .collection("Chat")
     .document("cF7DrENgQ4noWjr3SxKX")
     .get()
     .await()
     .result

launch 在您调用它的地方的协程:

launch {
    val owner = getOwner()
    // update the GUI
}

这假设您从 CoroutineScope.

对象调用 launch

第一个代码片段中 runBlocking{..} 的用法如下:runBlocking 函数 blocks 执行参数 lambda 代码(和 lambda代码将在内部暂停)。它的意义不大。

您可能希望使用 launch{..} 函数启动协程,并使用 withContext(Dispatchers.Main){..} 使块在 UI 线程中执行,例如显示获取的结果。您也可以在 activity class.

中实现 CoroutineScope

第一步 - 您需要将 Firebase API 调用转换为挂起函数。它可以用 suspendCoroutine{..} 函数来完成(在 kotlinx.coroutines 库中还有几个像 suspendCancellableCoroutine{..} 的函数。

有一个带有 Google Play Services 的集成库,为 Firebase
提供支持 https://github.com/Kotlin/kotlinx.coroutines/tree/master/integration/kotlinx-coroutines-play-services

 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"