https://kotlinlang.org logo
Title
j

John O'Reilly

05/23/2022, 5:41 PM
Am looking at some code like following....a function in a view model that creates a
StateFlow
using
stateIn
(which is called/collected from Fragment)...seemingly it work but feels like there's an issue, or at least some redundancy here but can't put my finger on why right now? (reason that's it's a suspend function instead of property is that it needs to call
suspendFunctionReturningFlowB
here but probably other ways around that....)
suspend fun someFunction() = flowA.combine(suspendFunctionReturningFlowB()) { valA, valB ->
    <some logic>
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), null)
It at least seems like there would only by definition be one subscriber so perhaps use of
stateIn
etc redudant?
y

yschimke

05/23/2022, 5:46 PM
Yeah - that would be my concern.
the function instead of typical val would lead to multiple calls to it, each setting up the additional accounting work for state in, and while subscribed.
j

John O'Reilly

05/23/2022, 5:47 PM
yeah, I guess the typical use of StateFlow would be (a potentially self updating) property
y

yschimke

05/23/2022, 5:47 PM
I don't see why you can't just hide suspendFunctionReturningFlowB() inside the body of a flow {}.
it doesn't have a param from someFunction. It doesn't use results from flowA. Seems perfect for that.
j

John O'Reilly

05/23/2022, 5:49 PM
hmm, perhaps.....
suspendFunctionReturningFlowB
returns a flow (based internally though on call to suspend function)....and that returned flow is then combined with flowA
h

hfhbd

05/23/2022, 5:50 PM
but
suspendFunctionReturningFlowB
should not be suspend at all. No
Flow
returning function should be marked as
suspend
y

yschimke

05/23/2022, 5:50 PM
val someVal = flowA.combine(flow { emitAll(suspendFunctionReturningFlowB()) }) { valA, valB ->
    <some logic>
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), null)
j

John O'Reilly

05/23/2022, 5:53 PM
"No
Flow
returning function should be marked as
suspend"
Probably again can be done differently but that function is returning one of 2 flows based on result of call to a suspend function.
but....I have seen that guidance as well but didn't see very clear explanation of reason for it
@yschimke yeah, looks like that would work to
y

yschimke

05/23/2022, 6:01 PM
Not sure about the rule, but it's hard to reason about when these are mixed. IMHO In the Flow world, things should be cheap and usually not have side effects until you subscribe. It's hard when APIs mix them. Seen a few ListenableFuture apis that do blocking work then return Futures.immediateValue(x). It's not that, but I think the API types (colors) should make it clear exactly how to use it. Would be interested to here the correct answer though.
j

John O'Reilly

05/23/2022, 6:03 PM
Yeah, agreed that it's much simpler if they're not mixed like that
h

hfhbd

05/23/2022, 6:21 PM
You should wrap the suspend call in
flow { if(suspending()) emitAll(flow1) else emitAll(flow2) }
then 🙂
☝️ 1
👍 2
u

uli

05/24/2022, 6:04 AM
Maybe you can implement suspendFunctionReturningFlow wit h flatMapLatest?