Sometimes my domain needs `suspend` functions, som...
# coroutines
n
Sometimes my domain needs
suspend
functions, sometime it needs `Flow`s, so most of the time I just code the
Flow
implementations of the Repository interfaces (which are consumed by my domain), and just use
Flow.first()
to "transform" the flow to a suspending function. But it feels weird. I guess, performance wise, that the implementation of a suspending function can be more performant than the Flow one (+ first()). Even more if the Flow is constructed via a
callbackFlow
or other Channel-backed flows (which seem "heavier"). I have no metrics tho. What are you thoughts ?
k
Flow.first
can potentially just be wrong. Especially in the case where a Flow is amended to include an
onStart { emit(default) }
y
True for patterns like StateFlow. I guess using first requires understanding the impl.
It's not possible to optimise the first to be the same as suspending. It's an extension function based on just the properties of Flow. So you have to assume it's slightly less efficient in typical cases.
But maybe possible to regain that with some optimisations that work for flow, like shared flow?
e
first
doesn't introduce any extra suspension
flow.first()
behaves similarly to
Copy code
lateinit var result
try {
    flow.collect {
        result = it
        throw Exception()
    }
} catch (_: Exception) {
    return result
}
the real implementation handles more corner cases but that's the basic idea
y
If you query Room, the suspend call can read from disk or cache once.
I'm assuming the flow needs to register listeners and process deltas
I don't know the suspend call is cheaper than flow.first() but if not it would be a good performance win to fix.
u
Sometimes my domain needs
suspend
functions, sometime it needs `Flow`s,
Do you mean 1. the same data source is sometimes used reactive and somtimes just read? 2. some sources are single value, some streams? If 2), I’d strongly suggest to make that visible and declare the single value sources (i.e. retrofit calls) as suspend functions. If it is 1., excessive use of
first
in a reactive environment could be a red flag that indicates an inconsistent architecture. Why not go fully reactive? If your use of `first`is rare then don’t worry about optimization.
y
There are definitely one shot type events where you don't want the flow. Say a WorkManager job, or generating a notification.