I'm trying to implement One Tap, so I have created a function that looks like this:
override suspend fun oneTapSgnInWithGoogle() = flow {
try {
emit(Result.Loading)
val result = oneTapClient.beginSignIn(signInRequest).await()
emit(Result.Success(result))
} catch (e: Exception) {
Log.d(TAG, "oneTapSgnInWithGoogle: ${e.message}")
emit(Result.Error(e.message!!))
}
}
If I use flow and try to emit the result, my app crashed with the following message:
Flow exception transparency is violated: StandaloneCoroutine has completed normally; but then emission attempt of value 'Error(message=StandaloneCoroutine has completed normally)' has been detected.
However, if change the code to:
override suspend fun oneTapSgnInWithGoogle() = channelFlow {
try {
send(Result.Loading)
val result = oneTapClient.beginSignIn(signInRequest).await()
send(Result.Success(result))
} catch (e: Exception) {
Log.d(TAG, "oneTapSgnInWithGoogle: ${e.message}")
send(Result.Error(e.message!!))
}
}
And I use channelFlow and try to send the result, the app isn't crashing but I still get the error message saying:
StandaloneCoroutine has completed normally
How can I emit the result correctly and get rid of this error message?
P.S. In my ViewModel class I use:
fun oneTapSgnInWithGoogle() = liveData(Dispatchers.IO) {
viewModelScope.launch {
repo.oneTapSgnInWithGoogle().collect { result ->
emit(result)
}
}
}
This is not a good practice to launch a coroutine in
liveDatablock.liveDatablock is asuspendlambda, you can collect values directly in it without launching a coroutine:In your case
liveDatablock has already finished execution (and corresponding coroutine, in whichliveDatablock is executed) when you try to emit a value toLiveData. The solution above should solve the problem.