Jetpack Compose4 min read

remember vs rememberSaveable in Jetpack Compose 🤔

If you've ever built a screen in Jetpack Compose and wondered why your state resets on rotation or process death, you've probably hit the remember vs rememberSaveable confusion. Let's break it down.

September 15, 2025By Divya

remember 🧠

Stores state only in memory.

Survives recompositions.

BUT… lost on configuration changes (rotation, dark mode toggle) or process death.

var text by remember { mutableStateOf("") }

👉 Good for ephemeral UI state (scroll position, animations, toggles).

rememberSaveable 💾

Stores state in memory + Bundle (or custom saver).

Survives recompositions and config changes.

Restores automatically after process death.

var text by rememberSaveable { mutableStateOf("") }

👉 Use for user inputs (form fields, text, selections) that should persist across rotations.

When rememberSaveable Fails

Custom objects need custom savers:

// ❌ This won't work - custom objects need custom savers
data class User(val name: String, val age: Int)
var user by rememberSaveable { mutableStateOf(User("", 0)) } // Crashes!

// ✅ This works - with custom saver
var user by rememberSaveable(
    saver = Saver(
        save = { mapOf("name" to it.name, "age" to it.age) },
        restore = { User(it["name"] as String, it["age"] as Int) }
    )
) { mutableStateOf(User("", 0)) }

Performance Consideration

rememberSaveable has slight overhead since it serializes to Bundle, so don't use it for frequently changing states like animation values.

Quick Decision Tree

  • Text input, form data, user selectionsrememberSaveable
  • Animation states, scroll positions, temporary UI flagsremember
  • Custom objectsremember + manual save/restore OR custom saver

Real-World Examples

Form Input (Use rememberSaveable)

@Composable
fun LoginForm() {
    var email by rememberSaveable { mutableStateOf("") }
    var password by rememberSaveable { mutableStateOf("") }

    Column {
        TextField(
            value = email,
            onValueChange = { email = it },
            label = { Text("Email") }
        )
        TextField(
            value = password,
            onValueChange = { password = it },
            label = { Text("Password") }
        )
    }
}

Animation State (Use remember)

@Composable
fun AnimatedButton() {
    var isPressed by remember { mutableStateOf(false) }
    val scale by animateFloatAsState(
        targetValue = if (isPressed) 0.9f else 1f
    )

    Button(
        modifier = Modifier
            .scale(scale)
            .pointerInput(Unit) {
                detectTapGestures(
                    onPress = {
                        isPressed = true
                        tryAwaitRelease()
                        isPressed = false
                    }
                )
            },
        onClick = { }
    ) {
        Text("Press me")
    }
}

TL;DR ⚡

Use remember for short-lived UI states.

Use rememberSaveable when the state matters across rotations or process death.

Think of it like this:
🧠 remember = memory only
💾 rememberSaveable = memory + save/restore

Wrapping Up

The key is understanding the lifecycle of your state and choosing the right tool for the job. When in doubt, ask yourself: "Would my users be frustrated if this state disappeared after a rotation?" If yes, use rememberSaveable.

What state management patterns have you found most useful in Compose? Share your experiences!