0

I have function:

@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() }
   }

When i want to use it second time code is not called. I tested another function with only Log.d inside and had the same problem.

pat20036
  • 83
  • 6

1 Answers1

4

A flow is a type that can emit multiple values sequentially. An addOnSuccessListener or addOnFailureListener would emit their results just once. So what you probably want to use is a suspendCancellableCoroutine builder that can be used for one-shot requests.

Here's what that might look like:

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))
        }
    }

And you can call it in any coroutine scope (e.g viewModelScope) like so:

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

Side benefit: You don't have to use the @ExperimentalCoroutinesApi decorator ;).

EDIT

If you're using await then you're already using Firestore with coroutines. So there's no need to use any coroutine builder, just call the suspended function without the addOnSuccessListener and addOnFailureListener

override suspend fun checkIsPostLiked(userId: String, postId: String): FirebaseEventResponse = 
        try { 
          FirebaseFirestore.getInstance()
            .collection(postCollection)
            .document(postId)
            .get()
            .await()
        } catch (e: Exception) {
            // handle exception
        }
    }
Tobi Daada
  • 528
  • 2
  • 8
  • OP is already calling [await](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-play-services/kotlinx.coroutines.tasks/com.google.android.gms.tasks.-task/await.html), which does pretty much this already AFAICT. – Joffrey Jun 07 '21 at 13:05
  • @Joffrey thanks for pointing that out. I've updated my answer. – Tobi Daada Jun 07 '21 at 13:12