or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

collections.mdcomposition.mdeffects.mdindex.mdstate-management.md

state-management.mddocs/

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

```