Coroutines callbackFlow 的代码只被调用一次

Code from Coroutines callbackFlow is called only one time

我有功能:

@ExperimentalCoroutinesApi
    override suspend fun checkIsPostLiked(userId: String, postId: String): Flow<FirebaseEventResponse> = callbackFlow {
            try {
            FirebaseFirestore.getInstance().collection(postCollection).document(postId).get().addOnSuccessListener {
                trySend(SuccessDocument(it))
            }.addOnFailureListener {
                trySend(ExceptionEvent(it))
            }.await()
        } catch (e: Exception) {
            trySend(ExceptionEvent(e))
        }
        awaitClose { this.cancel() }
   }

当我想第二次使用它时,代码没有被调用。我测试了另一个只有 Log.d 的函数,但遇到了同样的问题。

流是一种类型 that can emit multiple values sequentiallyaddOnSuccessListeneraddOnFailureListener 只会发出一次结果。因此,您可能想要使用的是 suspendCancellableCoroutine 可用于一次性请求的构建器。

这可能是这样的:

override suspend fun checkIsPostLiked(userId: String, postId: String): FirebaseEventResponse = suspendCancellableCoroutine { continuation ->
        try {
            FirebaseFirestore.getInstance().collection(postCollection).document(postId).get().addOnSuccessListener {
                continuation.resume(SuccessDocument(it), null)
            }.addOnFailureListener {
                continuation.resumeWithException(ExceptionEvent(it))
            } 
        } catch (e: Exception) {
            continuation.resumeWithException(ExceptionEvent(e))
        }
    }

您可以在任何协程范围(例如 viewModelScope)中调用它,如下所示:

viewModelScope.launch {
  try {
    val isPostLiked = checkIfPostIsLiked(userId, postId)
  } catch(e: Exception) {
    // handle exception
  }
}

附带好处:您不必使用 @ExperimentalCoroutinesApi 装饰器 ;)。

编辑

如果您正在使用 await,那么您已经在使用 Firestore 和协程。所以不需要使用任何协程构建器,只需调用没有 addOnSuccessListeneraddOnFailureListener

的挂起函数
override suspend fun checkIsPostLiked(userId: String, postId: String): FirebaseEventResponse = 
        try { 
          FirebaseFirestore.getInstance()
            .collection(postCollection)
            .document(postId)
            .get()
            .await()
        } catch (e: Exception) {
            // handle exception
        }
    }