State in Jetpack Compose: The UI's Memory

In Compose, state is any value that can change over time. The UI is a direct function of this state; when the state updates, the UI automatically redraws (recomposes) to match. The main footgun is not "hoisting" state, which makes components hard to test.
WHY IT EXISTS Traditional Android UI required developers to manually find and update individual UI elements. Compose was designed to eliminate this manual work. Instead of telling the UI how to change, you simply describe what the UI should look like for a given state, and Compose handles the updates automatically.
THE MENTAL MODEL State is any value that can change over time and affect what the user sees. Your UI is a pure function of that state: UI = f(state). When the data changes, Compose intelligently redraws (recomposes) only the parts of the UI that depend on that specific data. You don't tell a button to change its color; you change a state variable that the button's color reads from.
HOW IT WORKS A variable is declared as a state holder, often using remember { mutableStateOf(...) }. The remember function ensures the state survives across recompositions, while mutableStateOf makes it observable. When you update the value of this state object, Compose detects the change and schedules a recomposition for any composable that reads that state. This update cycle is the core of Compose's declarative nature.
WHEN TO USE IT State is fundamental for any interactive UI. Use it to manage user input in text fields, the checked status of a switch, a list of items fetched from an API, or the current tab the user has selected. The source mentions saving UI state, which is a key use case for handling events like device rotation without losing user data.
WHEN NOT TO USE IT Avoid making everything stateful. If a value can be calculated directly from other state during composition, don't store it in its own state variable. For example, a full name can be derived from first name and last name states without needing its own remember. Business logic and complex state should live in architectural components like a ViewModel, not directly in your composables.
ONE CANONICAL EXAMPLE The most important pattern is "state hoisting." Instead of a low-level composable like a custom Switch managing its own on/off state, you "hoist" that state to the parent composable that uses the switch. The parent holds the state and passes down the current value and a callback function to update it. This makes the Switch component stateless, reusable, and easy to test because its behavior is controlled entirely from the outside.
Read the original → developer.android.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.