Stylianos Gakis
08/20/2021, 1:38 PMStylianos Gakis
08/20/2021, 1:38 PMval viewModel: MyViewModel = hiltViewModel()
val lifecycleOwner = LocalLifecycleOwner.current
val stateFlow: Flow<ViewState> = viewModel.state
I can see all the following ways being viable, but I am not sure which one is best/preferable and which ones are straight up wrong in some scenarios, meaning there might be errors/crashes, or even simply inefficiencies.
Way #1
val viewState: ViewState by stateFlow.collectAsState(ViewState.Initial)
Way #2
val viewState: ViewState by remember(stateFlow, lifecycleOwner) {
stateFlow.flowWithLifecycle(lifecycleOwner.lifecycle)
}.collectAsState(initial = ViewState.Initial)
Way #3
val viewState: ViewState by produceState(
initialValue = ViewState.Initial,
stateFlow,
lifecycleOwner
) {
stateFlow.flowWithLifecycle(lifecycleOwner.lifecycle)
.collect { value = it }
}
Way #4
val rememberedFlow: Flow<ViewState> = remember(stateFlow, lifecycleOwner) {
stateFlow.flowWithLifecycle(lifecycleOwner.lifecycle)
}
val viewState3: ViewState by produceState(ViewState.Initial, rememberedFlow) {
rememberedFlow.flowWithLifecycle(lifecycleOwner.lifecycle)
.collect { value = it }
}
And I’m sure I’ve seen more than that of various complexities.
I am still not super comfortable with what I would be missing out on if I went with #3 instead of #4 for example, by not explicitly remembering the flow itself, am I missing out on performance?
In case of #1, the simplest one, is this totally wrong? If yes, why is it wrong? Does it have bugs? Is it simply inefficient?
So many questions, I would love to see an article or some docs on a definitive way to weigh those decisions and know what you are doing while doing so.Stylianos Gakis
08/20/2021, 1:46 PMcollectAsState
maybe was not a super good idea, and I would love to hear more about why and how we can make these informed decisions about what to do/not do.
Especially as long as lint checks are not there fully to help us avoid shooting ourselves in the foot (This lint check is a good example of one of them that is nice, but only available on the alpha compose channel as of right now)Albert Chang
08/20/2021, 1:48 PMflowWithLifecycle
is used mainly for safeness (to avoid modifying UI in the background). In compose it's totally ok to modifying states in the background, so as long as your flow doesn't emit frequently in the background I don't think there is much benefit really to use flowWithLifecycle
.Stylianos Gakis
08/20/2021, 1:51 PMAlbert Chang
08/20/2021, 1:53 PMStylianos Gakis
08/20/2021, 1:57 PMAdam Powell
08/20/2021, 2:01 PMAdam Powell
08/20/2021, 2:01 PMNick
08/20/2021, 2:02 PMAdam Powell
08/20/2021, 2:03 PMNick
08/20/2021, 2:03 PMNick
08/20/2021, 2:04 PMAdam Powell
08/20/2021, 2:04 PMflowWithLifecycle
is that it stops cold upstream flows from performing expensive work when your app is in the background. If you had a flow of GPS coordinates that turned the GPS on while collecting it, you don't want to leave that running for battery and privacy reasons.Adam Powell
08/20/2021, 2:27 PMcollectAsState
only starts a new collect on recomposition if the receiver is a different flow instance on recomposition. The most common reason for this is operator assembly