nglauber
10/28/2021, 5:15 PMFlow operator functions should not be invoked within composition
Basically, almost all flows of my app are using something like this:
val someStateInViewModel by viewModel.myState.flowInLifecycle()
.collectAsState(initial = null)
This flowInLifecycle
function is doing the following:
@Composable
fun <T> Flow<T>.flowInLifecycle(): Flow<T> {
val lifecycleOwner = LocalLifecycleOwner.current
return remember(this, lifecycleOwner) {
this.flowWithLifecycle(lifecycleOwner.lifecycle, Lifecycle.State.STARTED)
}
}
Any suggestion? Because I’m using this function is 225 places in my app 😭Will Shelor
10/29/2021, 2:18 AMnglauber
10/29/2021, 3:20 AMEven if Compose doesn’t recompose the UI when the host activity or fragment is in the background, the flow producer is still active and can waste resources. Compose can suffer from the same problem as the View system.
When collecting flows in Compose, use theoperator as follows:Flow.flowWithLifecycle
tad
10/29/2021, 3:27 AMFlow
objects on every recomposition. Your operator doesn't do that (it uses remember
under the hood), but it also doesn't do anything collectAsState
doesn't already do, as the coroutine scope it uses doesn't outlive LifecycleScope.
If you're using StateFlow then no other operator is required to keep it hot for multiple collectors, but if you want to avoid creating a hot flow for each collector, use shareIn(viewModelScope)
with the appropriate restart policy in the ViewModel.nglauber
10/29/2021, 3:44 AMStateFlow
in my viewmodel, so I think I’m good 🙂Adam Powell
10/29/2021, 1:29 PM@Composable
we could assume you know what you're doing w.r.t. avoiding recomposition causing a cancel/re-collect for a new Flow instance