0
# State Management
1
2
Core state management APIs for creating reactive UI state that automatically triggers recomposition when values change. The Compose state system enables declarative UI updates through observable state holders.
3
4
## Capabilities
5
6
### State Interfaces
7
8
The fundamental interfaces for state management in Compose.
9
10
```kotlin { .api }
11
/**
12
* Read-only state holder that can be observed by composables
13
*/
14
interface State<out T> {
15
val value: T
16
}
17
18
/**
19
* Mutable state holder that triggers recomposition when changed
20
*/
21
interface MutableState<T> : State<T> {
22
override var value: T
23
}
24
```
25
26
### Creating Mutable State
27
28
Create mutable state instances that trigger recomposition when their values change.
29
30
```kotlin { .api }
31
/**
32
* Creates a mutable state holder with the specified initial value
33
* @param value Initial value for the state
34
* @param policy Mutation policy for detecting changes (default: structural equality)
35
* @return MutableState instance
36
*/
37
fun <T> mutableStateOf(
38
value: T,
39
policy: SnapshotMutationPolicy<T> = structuralEqualityPolicy()
40
): MutableState<T>
41
```
42
43
**Usage Examples:**
44
45
```kotlin
46
import androidx.compose.runtime.*
47
import androidx.compose.runtime.derivedStateOf
48
49
@Composable
50
fun StateExample() {
51
// Create mutable state
52
val count = mutableStateOf(0)
53
val text = mutableStateOf("Hello")
54
55
// Access values
56
Text("Count: ${count.value}")
57
Text("Text: ${text.value}")
58
59
// Update values
60
Button(onClick = { count.value++ }) {
61
Text("Increment")
62
}
63
64
Button(onClick = { text.value = "Updated!" }) {
65
Text("Update Text")
66
}
67
}
68
```
69
70
### State Delegation
71
72
Use property delegation for cleaner syntax with state values.
73
74
```kotlin { .api }
75
/**
76
* Delegate operator for reading state values
77
*/
78
operator fun <T> State<T>.getValue(
79
thisObj: Any?,
80
property: KProperty<*>
81
): T
82
83
/**
84
* Delegate operator for writing mutable state values
85
*/
86
operator fun <T> MutableState<T>.setValue(
87
thisObj: Any?,
88
property: KProperty<*>,
89
value: T
90
)
91
```
92
93
**Usage Examples:**
94
95
```kotlin
96
@Composable
97
fun DelegationExample() {
98
// Using delegation with 'by' keyword
99
var count by mutableStateOf(0)
100
var isEnabled by mutableStateOf(true)
101
var userName by mutableStateOf("")
102
103
// Direct access without .value
104
Text("Count: $count")
105
Text("Enabled: $isEnabled")
106
107
Button(
108
onClick = { count++ },
109
enabled = isEnabled
110
) {
111
Text("Click me")
112
}
113
114
TextField(
115
value = userName,
116
onValueChange = { userName = it }
117
)
118
}
119
```
120
121
### Remember State
122
123
Preserve state across recompositions using the remember API.
124
125
```kotlin { .api }
126
/**
127
* Remembers a value across recompositions
128
* @param calculation Function to create the remembered value
129
* @return The remembered value
130
*/
131
@Composable
132
fun <T> remember(calculation: () -> T): T
133
134
/**
135
* Remembers a value with dependency keys for conditional invalidation
136
* @param key1 Dependency key - value is recalculated when this changes
137
* @param calculation Function to create the remembered value
138
* @return The remembered value
139
*/
140
@Composable
141
fun <T> remember(key1: Any?, calculation: () -> T): T
142
143
/**
144
* Remembers a value with multiple dependency keys
145
*/
146
@Composable
147
fun <T> remember(
148
key1: Any?,
149
key2: Any?,
150
calculation: () -> T
151
): T
152
153
/**
154
* Remembers a value with variable number of dependency keys
155
*/
156
@Composable
157
fun <T> remember(
158
vararg keys: Any?,
159
calculation: () -> T
160
): T
161
```
162
163
**Usage Examples:**
164
165
```kotlin
166
@Composable
167
fun RememberExample(userId: String) {
168
// Remember state across recompositions
169
val counter by remember { mutableStateOf(0) }
170
171
// Remember with key - recalculated when userId changes
172
val userProfile by remember(userId) {
173
mutableStateOf(loadUserProfile(userId))
174
}
175
176
// Remember expensive computations
177
val expensiveData by remember(userId) {
178
mutableStateOf(performExpensiveCalculation(userId))
179
}
180
181
// Multiple keys
182
val complexState by remember(userId, counter) {
183
mutableStateOf(createComplexState(userId, counter))
184
}
185
}
186
```
187
188
### Mutation Policies
189
190
Control how the state system detects changes using mutation policies.
191
192
```kotlin { .api }
193
/**
194
* Policy interface for detecting state mutations
195
*/
196
interface SnapshotMutationPolicy<T> {
197
fun equivalent(a: T, b: T): Boolean
198
fun merge(previous: T, current: T, applied: T): T?
199
}
200
201
/**
202
* Built-in policy using structural equality (==)
203
*/
204
fun <T> structuralEqualityPolicy(): SnapshotMutationPolicy<T>
205
206
/**
207
* Built-in policy using referential equality (===)
208
*/
209
fun <T> referentialEqualityPolicy(): SnapshotMutationPolicy<T>
210
211
/**
212
* Policy that treats all values as different (always triggers updates)
213
*/
214
fun <T> neverEqualPolicy(): SnapshotMutationPolicy<T>
215
```
216
217
**Usage Examples:**
218
219
```kotlin
220
@Composable
221
fun PolicyExample() {
222
// Default structural equality
223
var items by mutableStateOf(listOf("a", "b", "c"))
224
225
// Referential equality - only updates on reference change
226
var objectState by mutableStateOf(
227
MyObject("data"),
228
referentialEqualityPolicy()
229
)
230
231
// Never equal - always triggers updates
232
var alwaysUpdate by mutableStateOf(
233
getCurrentTimestamp(),
234
neverEqualPolicy()
235
)
236
}
237
```
238
239
### Saveable State
240
241
State that survives configuration changes and process death.
242
243
```kotlin { .api }
244
/**
245
* Remembers state that can survive configuration changes
246
* @param inputs Dependency keys for conditional restoration
247
* @param saver Custom saver for non-primitive types
248
* @param init Function to create initial value
249
* @return Saveable state value
250
*/
251
@Composable
252
fun <T> rememberSaveable(
253
vararg inputs: Any?,
254
saver: Saver<T, out Any> = autoSaver(),
255
init: () -> T
256
): T
257
```
258
259
**Usage Examples:**
260
261
```kotlin
262
import androidx.compose.runtime.saveable.rememberSaveable
263
264
@Composable
265
fun SaveableExample() {
266
// Survives configuration changes
267
var text by rememberSaveable { mutableStateOf("") }
268
var count by rememberSaveable { mutableStateOf(0) }
269
270
// Custom saver for complex objects
271
var customObject by rememberSaveable(
272
saver = CustomObjectSaver
273
) {
274
mutableStateOf(CustomObject())
275
}
276
277
TextField(
278
value = text,
279
onValueChange = { text = it }
280
)
281
282
Button(onClick = { count++ }) {
283
Text("Count: $count")
284
}
285
}
286
```
287
288
## Advanced State Management
289
290
### Derived State
291
292
Create state that depends on other state values.
293
294
```kotlin { .api }
295
/**
296
* Creates derived state that updates when dependencies change
297
*/
298
@Composable
299
fun <T> derivedStateOf(calculation: () -> T): State<T>
300
```
301
302
**Usage Examples:**
303
304
```kotlin
305
@Composable
306
fun DerivedStateExample() {
307
var firstName by remember { mutableStateOf("") }
308
var lastName by remember { mutableStateOf("") }
309
310
// Derived state automatically updates when dependencies change
311
val fullName by remember {
312
derivedStateOf { "$firstName $lastName".trim() }
313
}
314
315
val isFormValid by remember {
316
derivedStateOf {
317
firstName.isNotBlank() && lastName.isNotBlank()
318
}
319
}
320
321
Text("Full name: $fullName")
322
Button(
323
onClick = { saveUser(fullName) },
324
enabled = isFormValid
325
) {
326
Text("Save")
327
}
328
}
329
```
330
331
### State Production
332
333
Produce state from asynchronous sources.
334
335
```kotlin { .api }
336
/**
337
* Produces state from a suspending producer function
338
* @param initialValue Initial value while producer is running
339
* @param producer Suspending function that produces values
340
* @return State holding the produced value
341
*/
342
@Composable
343
fun <T> produceState(
344
initialValue: T,
345
vararg keys: Any?,
346
producer: suspend ProduceStateScope<T>.() -> Unit
347
): State<T>
348
349
/**
350
* Scope for producing state values
351
*/
352
interface ProduceStateScope<T> : MutableState<T>, CoroutineScope {
353
suspend fun awaitDispose(onDispose: () -> Unit)
354
}
355
```
356
357
**Usage Examples:**
358
359
```kotlin
360
@Composable
361
fun ProduceStateExample(url: String) {
362
// Produce state from async operation
363
val imageState by produceState<ImageBitmap?>(null, url) {
364
value = loadImageFromUrl(url)
365
}
366
367
val userData by produceState(UserData.Loading, userId) {
368
try {
369
value = UserData.Success(loadUser(userId))
370
} catch (e: Exception) {
371
value = UserData.Error(e.message)
372
}
373
}
374
375
when (val data = userData) {
376
is UserData.Loading -> CircularProgressIndicator()
377
is UserData.Success -> UserProfile(data.user)
378
is UserData.Error -> ErrorMessage(data.message)
379
}
380
}
381
```