Home > Blockchain >  How to use remember & mutableStateOf seperately?
How to use remember & mutableStateOf seperately?

Time:06-15

Usually, compose codes are like

@Preview
@Composable
fun BuildMyView() {
    val counter = rememberSaveable { mutableStateOf(1) }

    Text(
        modifier = Modifier
            .fillMaxSize()
            .wrapContentSize(align = Alignment.Center)
            .clickable { counter.value   },// click and text will   
        text = "${counter.value}"
    )
}

Recently, I want to collect all view data together and build a state and create sth like:

data class MyState(
    val data: MutableState<String>
)

val stateTemp = MyState(mutableStateOf("hello"))

@Preview
@Composable
fun BuildMyView() {
    val counter = rememberSaveable { stateTemp.data}

    Text(
        modifier = Modifier
            .fillMaxSize()
            .wrapContentSize(align = Alignment.Center)
            .clickable { stateTemp.data.value  = "-1" },
        text = counter.value
    )
}

In second case, when I click text, it does but if I go to a new page and come back, all changes will lost however in first case it doesn't.

I then read some compose codes and get confusing since I didn't find where remember subscribe a mutable state.

Is there a method to make mutable state out of compose work?

Beside, is somewhere I can find codes generated by compose under my gradle build dir or anywhere else (except dex, that's too hard to read)? Compose really did amazing job but I cannot read the real codes running and that makes much more difficult for freshman to get start.

UPDATE ON 2022/6/15

Now I found a proper solution to use viewmodel instead of state holder and use mutableState in viewmodel and subscribe state in view composable part so that I can avoid complex grammar of viewmodel with livedata. Hope that will help followers.

CodePudding user response:

I then read some compose codes and get confusing since I didn't find where remember subscribe a mutable state.

As far as I understand, remember calculates and caches what ever is inside its lambda during the first composition or first execution of the @composable function only, this is the only thing that the @composable remembers or subscribes on. Unless you provide a key to a remember, that when it changed, it will trigger a re-calculation to be remembered

Is there a method to make mutable state out of compose work?

Do you mean some piece of non composable code or function that will automatically trigger when this State object is changed? If this is what you mean, I suppose you just have to resort back to good old observable patterns

As far as I understand, compose States are specifically designed to work with the underlying Snapshot system where the heart of triggering the composition mechanism happens, I can't imagine (so far) any usage of State objects outside of composition or outside of the Snapshot system.

In second case, when I click text, it does but if I go to a new page and come back, all changes will lost however in first case it doesn't.

As for using rememberSaveable, I would be careful using it , it might look the same as remember with just an additional power of saving/restoration, but it has more power with equal responsibilities imposed to it that you have to take into account when using it. I haven't used or defined a rememberSaveable object without defining a Saver in it explicitly, so I can only assume in your case here

rememberSaveable { mutableStateOf(1) }

the composable observes a rememberSaveable that also observes an actual object that actually changes and implicitly saves and restores that object with the most recent value

while in this, I think

data class MyState(
    val data: MutableState<String>
)

val stateTemp = MyState(mutableStateOf("hello"))
...
...
rememberSaveable { stateTemp.data}

rememberSaveable saves the state of the val data: MutableState<String> (which is empty), while the composable observes an instance of a mutableState that is changing, unfortunately rememberSaveable already saved an initial state in way like this rememberSaveable { data: MutableState<String> } not the actual mutableStateOf("hello") that changes, so it will restore it that way when you go back.

I'm curious, you can try implementing your MyState class with a companion object holding a Saver where you can define how rememberSaveable will Save and Restore the data, I think it will restore it when you navigate back to that screen. When you debug a Saver implementation, you will also notice that the restoration is invoked during recomposition. Im not quite sure though

Disclaimer: Im just learning compose recently and still digging deeper about the Snapshot system, and it seemed like you're heading in the same direction as I do. I'd recommend to visit this link once in a while if your'e interested in the Snapshot system. Apologies as well, I can't comment yet due to lack of reputation so I just posted my thought and current understanding of how State and composition work together.

  • Related