https://kotlinlang.org logo
#flow
Title
# flow
j

Jason Ankers

03/24/2021, 5:34 AM
How can I propagate an upstream exception in a SharedFlow? For example, I have an Android screen which combines multiple data sources:
val uiState = combine(sharedFlow1, sharedFlow2, sharedFlow2) { … }
and I would like to catch anything which goes wrong in any of the flows. How could I achieve that?
.catch
doesnt work because shared flows never complete
I’ve been considering creating a
Result
type which gets emitted from my shared flows, and create a flow extension
fun <T> Flow<Result<T>>.resultOrError()
which maps the errors to exceptions
w

wasyl

03/24/2021, 7:04 AM
A wrapper type is the proper solution. The docs for
SharedFlow
state
All errors and completion signals should be explicitly materialized if needed
j

Jason Ankers

03/24/2021, 7:39 AM
@wasyl Would something like this work?
Copy code
fun <T, U> Flow<Result<T, U>>.resultOrError(): Flow<T> { result ->
    return map { result ->
        when(result) {
            is Result.Success -> result.body
            is Result.Error -> throw Exception(result.error)
        }
    }
}
Copy code
val flow1 = flow { 
    // catch errors and convert to Result.Error
 }.shareIn(..).resultOrError()
val flow2 = flow { .. }.shareIn(..).resultOrError()
val combined = flow1.combine(flow2).catch(// handle errors)
w

wasyl

03/24/2021, 8:03 AM
I think so, yes. I’m not 100% sure but I think the shared flow will stay active though, because well it’s not completing. Overall if you’re using shared flow consider not converting to errors at all and only operating on the result class, but at first glance your snippet would work as you expect
j

Jason Ankers

03/24/2021, 8:05 AM
Yeah, the problem I found with working with a
Result
type is it’s not easy to quickly determine if anything failed during a large
combine
. I.e. if I’m combining 4 different data sources, I would need to individually check if each source is of type
Result.Error
.
catch
is a nice shortcut to grab any error
2 Views