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 sequentially。 addOnSuccessListener
或 addOnFailureListener
只会发出一次结果。因此,您可能想要使用的是 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
和协程。所以不需要使用任何协程构建器,只需调用没有 addOnSuccessListener
和 addOnFailureListener
的挂起函数
override suspend fun checkIsPostLiked(userId: String, postId: String): FirebaseEventResponse =
try {
FirebaseFirestore.getInstance()
.collection(postCollection)
.document(postId)
.get()
.await()
} catch (e: Exception) {
// handle exception
}
}
我有功能:
@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 sequentially。 addOnSuccessListener
或 addOnFailureListener
只会发出一次结果。因此,您可能想要使用的是 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
和协程。所以不需要使用任何协程构建器,只需调用没有 addOnSuccessListener
和 addOnFailureListener
override suspend fun checkIsPostLiked(userId: String, postId: String): FirebaseEventResponse =
try {
FirebaseFirestore.getInstance()
.collection(postCollection)
.document(postId)
.get()
.await()
} catch (e: Exception) {
// handle exception
}
}