I need to collect only the first value from two emitted by flow.
I have a function that returns flow:
fun myFlow = flow {
try {
emit(localDataSource.fetchData())
} catch(e: Exception) {
// just skip this error
}
emit(remoteDataSource.fetchData(1000, 0))
}
In one special case I need only first emitted value, doesn't matter is it from local cache or remote source. I tried this one:
fun getRandomFavoriteItem() = myFlow.first().filter { it.score > 7 }.randomOrNull()
But first() invocation always throws
java.lang.IllegalStateException: Flow exception transparency is violated: Previous 'emit' call has thrown exception kotlinx.coroutines.flow.internal.AbortFlowException: Flow was aborted, no more elements needed, but then emission attempt of value.
What I've tried:
- single() -
java.lang.IllegalArgumentException: Flow has more than one element
- take(1).first() -
java.lang.IllegalStateException: Flow exception transparency is violated: Previous 'emit' call has thrown exception kotlinx.coroutines.flow.internal.AbortFlowException: Flow was aborted, no more elements needed, but then emission attempt of value
- Catch error but it doesn't stop here:
myFlow.catch { e ->
if (e !is IllegalArgumentException) {
throw e
}
}.first().filter { it.score > 7 }.randomOrNull()
My questions are:
- What is the point of usage first() if it doesn't work in case of more than 1 emitted values? If I would know that my flow produces only one value I could just use any other terminal operator.
- How to avoid those errors and how to collect only first value without adding repeated code?