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.
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 selections →
rememberSaveable
- Animation states, scroll positions, temporary UI flags →
remember
- Custom objects →
remember
+ 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!