简体   繁体   English

firestore、协程和流

[英]firestore, coroutine and flow

firebase method is working on worker thread automatically. firebase 方法自动在工作线程上工作。 but I have used coroutine and callbackflow to implement firebase listener code synchronously or get return from the listener.但是我已经使用协程和回调流来同步实现 firebase 监听器代码或从监听器获取返回。 below is my code that I explained下面是我解释的代码

coroutine await with firebase for one shot协程等待与 firebase 一枪

override suspend fun checkNickName(nickName: String): Results<Int> {


    lateinit var result : Results<Int>

    fireStore.collection("database")
        .document("user")
        .get()
        .addOnCompleteListener { document ->


            if (document.isSuccessful) {

                val list = document.result.data?.get("nickNameList") as List<String>

                if (list.contains(nickName))
                    result = Results.Exist(1)
                else
                    result = Results.No(0)

                //document.getResult().get("nickNameList")
            }
            else {

            }
        }.await()

    return result
}

callbackflow with firebase listener带有 firebase 监听器的回调流

override fun getOwnUser(): Flow<UserEntity> = callbackFlow{

    val document = fireStore.collection("database/user/userList/")
        .document("test!!!!!")

    val subscription = document.addSnapshotListener { snapshot,_ ->

        if (snapshot!!.exists()) {

            val ownUser = snapshot.toObject<UserEntity>()

            if (ownUser != null) {
                trySend(ownUser)
            }
        }
    }

    awaitClose { subscription.remove() }

}

so I really wonder these way is good or bad practice and its reason所以我真的很想知道这些方式是好是坏的做法及其原因

Do not combine addOnCompleteListener with coroutines await() .不要将addOnCompleteListener与协程await()结合使用。 There is no guarantee that the listener gets called before or after await() , so it is possible the code in the listener won't be called until after the whole suspend function returns.不能保证在await()之前或之后调用侦听器,因此在整个挂起 function 返回之前,侦听器中的代码可能不会被调用。 Also, one of the major reasons to use coroutines in the first place is to avoid using callbacks.此外,首先使用协程的主要原因之一是避免使用回调。 So your first function should look like:所以你的第一个 function 应该如下所示:

override suspend fun checkNickName(nickName: String): Results<Int> {
    try {
        val userList = fireStore.collection("database")
            .document("user")
            .get()
            .await()
            .get("nickNameList") as List<String>

        return if (userList.contains(nickName)) Results.Exist(1) else Results.No(0)
    } catch (e: Exception) {
        // return a failure result here
    }
}

Your use of callbackFlow looks fine, except you should add a buffer() call to the flow you're returning so you can specify how to handle backpressure.您对callbackFlow的使用看起来不错,除了您应该向要返回的流添加一个buffer()调用,以便您可以指定如何处理背压。 However, it's possible you will want to handle that downstream instead.但是,您可能希望改为处理该下游。

override fun getOwnUser(): Flow<UserEntity> = callbackFlow {
    //...
}.buffer(/* Customize backpressure behavior here */)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM