y

    yschimke

    11 months ago
    If I'm using multiple MutableStateFlow instance fields for individual settable options of a composable, then using collectAsState inside the composable. Is there any guidance as to whether to use 6 individual fields, vs a single combined field with a data class. Do 6 State instances (of primitives, like Int / String) perform worse than a single State instance with that data class.
    I guess second question is if it's new code but stored as a instance field, can I swap between MutableStateFlow and mutableStateOf()? Is there much difference?
    Csaba Kozák

    Csaba Kozák

    11 months ago
    Personally i would not use
    mutableStateOf()
    in a ViewModel. Compose specific code should not leak into VMs.
    StateFlow
    is a better fit there.
    UIState object vs. multiple fields is an old debate, i do not think there is a consensus. 🙂 Performance wise, there should not be any difference, since you already read these 6 different streams, combining them into an object is not expensive.
    myanmarking

    myanmarking

    11 months ago
    I think he was asking about performance in like which ones minimize recompositions, rather than what is costly in creation of the flow.
    Csaba Kozák

    Csaba Kozák

    11 months ago
    Sorry, i missed that. The combined class could be suboptimal in that case, since if any of its 6 field change, the whole object will change, and compose has to recompose everything which reads the state object.
    Adam Powell

    Adam Powell

    11 months ago
    Prefer snapshot state, that is,
    mutableStateOf
    . Yes, in ViewModels too. Snapshots are not a UI or Compose-specific technology, it's a generic observable MVCC system.
    Multiple MutableStateFlows mean you can't ensure consistency across them in a thread-safe way. Single UiState objects in MutableStateFlows mean you're doing very broad recompositions from the root whenever things change instead of granular recompositions of only the things that change, and repeated .equals comparisons made by compose on stable objects can traverse large sections of that object tree multiple times as recomposition proceeds downward if you don't hit all the right optimization cases. Copying deep immutable object trees to make a change is cumbersome and usually means you're introducing something like arrow lenses to make it less obnoxious. Snapshots were literally created to solve these problems. Stop worrying what maven artifact they're delivered in and use them. 🙂
    Csaba Szugyiczki

    Csaba Szugyiczki

    11 months ago
    @Adam Powell How about decoupling the VM from the UI lifecycle. In this article we can see a way how to collect Flows from a VM in compose that respects the view lifecycle. If the Snapshot states are created in the VM how is it possible to handle lifecycle correctly without the VM knowing about it explicitly?
    Adam Powell

    Adam Powell

    11 months ago
    If you are truly using cold data sources then that matters, but if you have hot data sources (if you're using
    MutableStateFlow
    those are hot data sources) then doing any sort of lifecycle-bound collect isn't buying you much, if anything. Whatever process is changing the MutableStateFlow in response to other external stimuli is still running in the background unless you have some different means of limiting it.
    Csaba Szugyiczki

    Csaba Szugyiczki

    11 months ago
    I am not sure I can follow the reasoning perfectly. Can you show any code as reference, where snapshot state is created in the ViewModels. Did I miss a Compose sample app that does this?
    Adam Powell

    Adam Powell

    11 months ago
    It's the same as any of the hoisted state samples, just in a class that extends ViewModel.
    class MyViewModel : ViewModel() {
      var myValue by mutableStateOf(initial)
        private set // optional
    }
    Archie

    Archie

    11 months ago
    @Adam Powell I am not sure if I understood it correctly. In the original question of whether to use UIState object vs. multiple fields, is it correct to assume that having multiple fields with snapshot state is better? I’ve been working on Kotlin Multiplatform Projects where we share ViewModel across platform and so we do not use
    mutableStateOf
    inside the ViewModel. Is this assumption correct?