When to use remember and rememberSaveable in Jetpack Compose

For managing state within composables you can use remember but also rememberSaveable.

First of all, what happens if you do not use remember and rememberSaveable as well? Let’s look at the following code.

@Composable
fun Counter() {
   val count = mutableStateOf(0)
   Text(text = "Counter is $count.value")
   Button(onClick = {
      count.value++
   }) {
      Text(text = "Increment counter")
   }
}Code-Sprache: JavaScript (javascript)

In this composable function named Counter we have a simple textfield and a button. Every time we click the button, the textfield should show us the increment of the counter value which initially is 0.

But what happens when you click the button?

Nothing happens. The reason is, after clicking the button, the view will be recomposed and all values are set to their initial value again. The current state of the counter value (which should be 1) is not kept.

This is why we use remember in our composables. To remember their current state.

You need to save your state while recomposition

With the remember function we can avoid this and keep the previous state of the value. So if you use remember in the code sample above, you will see that the value increases by 1 when clicking the button as expected.

@Composable
fun Counter() {
   var count by remember { mutableStateOf(0) }
   Text(text = "Counter is $count")
   Button(onClick = {
      count++
   }) {
      Text(text = "Increment counter")
   }
}Code-Sprache: JavaScript (javascript)

Now the behavior is like expected. After clicking the button, the value is incremented.

But what happens if you make a configuration change on your device. You could for example rotate your device’s screen or switch from light to dark mode. Then the value will be reset to 0 again. Why is this the case?

remember() doesn’t keep any data on configuration state.

Let your state also survive configuration changes

RememberSavable can do this since it implements SavedStateHandle logic. So data like primitive ones or all values that are parcelizable remain their state after configuration change.

@Composable
fun Counter() {
   var count by rememberSaveable { mutableStateOf(0) }
   Text(text = "Counter is $count")
   Button(onClick = {
      count++
   }) {
      Text(text = "Increment counter")
   }
}Code-Sprache: JavaScript (javascript)

Now, if you click the button, the value will be incremented. Besides that, if you rotate your device, the value will remain.

Nevertheless most of the time you should avoid using rememberSavable. You should handle your state in Android ViewModel since everything related to that will survice configuration changes as well.

Of course if you have a very simple app you can also skip the ViewModel and put your code directly into the composable.

But if you want to stick to clean architecture and you want clear separation of concerns I would always recommend to use a ViewModel for state handling.