or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

composition-lifecycle.mdcomposition-local.mdeffects.mdindex.mdios-integration.mdsnapshot-system.mdstate-management.md

composition-lifecycle.mddocs/

0

# Composition and Lifecycle

1

2

Composition management and lifecycle control for building and managing UI component trees. Handles component creation, updates, disposal, and memory management throughout the lifecycle of composable functions.

3

4

## Capabilities

5

6

### Composable Annotation

7

8

The fundamental annotation that marks functions as composable, enabling them to participate in the Compose runtime.

9

10

```kotlin { .api }

11

/**

12

* Marks a function as composable, allowing it to call other composable functions

13

* and participate in recomposition

14

*/

15

@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE)

16

@Retention(AnnotationRetention.BINARY)

17

annotation class Composable

18

```

19

20

**Usage Examples:**

21

22

```kotlin

23

@Composable

24

fun MyButton(

25

text: String,

26

onClick: () -> Unit,

27

modifier: Modifier = Modifier

28

) {

29

Button(onClick = onClick, modifier = modifier) {

30

Text(text)

31

}

32

}

33

34

@Composable

35

fun UserProfile(user: User) {

36

Column {

37

Text("Name: ${user.name}")

38

Text("Email: ${user.email}")

39

MyButton("Edit Profile", onClick = { /* edit logic */ })

40

}

41

}

42

```

43

44

### Remember Functions

45

46

Functions for persisting values across recompositions, essential for maintaining state and expensive computations.

47

48

```kotlin { .api }

49

/**

50

* Remembers a value across recompositions with no keys

51

* @param calculation Function to compute the initial value

52

* @return The remembered value

53

*/

54

inline fun <T> remember(crossinline calculation: () -> T): T

55

56

/**

57

* Remembers a value with one key dependency

58

* @param key1 Key that determines when to recalculate

59

* @param calculation Function to compute the value

60

* @return The remembered value, recalculated when key changes

61

*/

62

inline fun <T> remember(

63

key1: Any?,

64

crossinline calculation: () -> T

65

): T

66

67

/**

68

* Remembers a value with two key dependencies

69

* @param key1 First key dependency

70

* @param key2 Second key dependency

71

* @param calculation Function to compute the value

72

* @return The remembered value, recalculated when any key changes

73

*/

74

inline fun <T> remember(

75

key1: Any?,

76

key2: Any?,

77

crossinline calculation: () -> T

78

): T

79

80

/**

81

* Remembers a value with three key dependencies

82

* @param key1 First key dependency

83

* @param key2 Second key dependency

84

* @param key3 Third key dependency

85

* @param calculation Function to compute the value

86

* @return The remembered value, recalculated when any key changes

87

*/

88

inline fun <T> remember(

89

key1: Any?,

90

key2: Any?,

91

key3: Any?,

92

crossinline calculation: () -> T

93

): T

94

95

/**

96

* Remembers a value with multiple key dependencies

97

* @param keys Variable number of key dependencies

98

* @param calculation Function to compute the value

99

* @return The remembered value, recalculated when any key changes

100

*/

101

inline fun <T> remember(

102

vararg keys: Any?,

103

crossinline calculation: () -> T

104

): T

105

```

106

107

**Usage Examples:**

108

109

```kotlin

110

@Composable

111

fun ExpensiveComputationExample(data: List<Int>) {

112

// Remember expensive computation result

113

val processedData = remember(data) {

114

data.map { it * it }.sorted() // Only recalculates when data changes

115

}

116

117

// Remember object creation

118

val textStyle = remember {

119

TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Bold)

120

}

121

122

// Remember with multiple keys

123

val filteredItems = remember(data, filter, sortOrder) {

124

data.filter(filter).sortedWith(sortOrder)

125

}

126

127

LazyColumn {

128

items(processedData) { item ->

129

Text("$item", style = textStyle)

130

}

131

}

132

}

133

```

134

135

### Recomposition Control

136

137

Functions and interfaces for controlling when and how recomposition occurs.

138

139

```kotlin { .api }

140

/**

141

* Returns the current recompose scope, which can be used to invalidate the current composition

142

* @return Current RecomposeScope or null if not in composition

143

*/

144

val currentRecomposeScope: RecomposeScope?

145

146

/**

147

* Interface for controlling recomposition of a specific scope

148

*/

149

interface RecomposeScope {

150

/**

151

* Invalidates this scope, causing it to be recomposed on the next recomposition

152

*/

153

fun invalidate()

154

}

155

156

/**

157

* Invalidates the current recompose scope, causing recomposition

158

*/

159

fun invalidate(): Unit

160

```

161

162

**Usage Examples:**

163

164

```kotlin

165

@Composable

166

fun ManualRecompositionExample() {

167

val scope = currentRecomposeScope

168

169

Button(onClick = {

170

// Manually trigger recomposition

171

scope?.invalidate()

172

}) {

173

Text("Force Recompose")

174

}

175

}

176

```

177

178

### Composition Context

179

180

Classes for managing composition execution and hierarchy.

181

182

```kotlin { .api }

183

/**

184

* Context for composition operations, providing access to composition-wide state

185

*/

186

abstract class CompositionContext {

187

/** Unique identifier for this composition context */

188

abstract val id: Int

189

190

/** Parent composition context, if any */

191

abstract val parent: CompositionContext?

192

}

193

194

/**

195

* Represents a composition tree and its lifecycle

196

*/

197

interface Composition {

198

/** Applies changes to the composition */

199

fun applyChanges()

200

201

/** Disposes the composition and releases resources */

202

fun dispose()

203

204

/** Whether this composition has pending changes */

205

val hasInvalidations: Boolean

206

}

207

208

/**

209

* A Composition that provides additional control over composition execution

210

*/

211

interface ControlledComposition : Composition {

212

/** Composes the composition with the given content */

213

fun compose(content: @Composable () -> Unit)

214

215

/** Forces recomposition of invalidated content */

216

fun recompose(): Boolean

217

218

/** Number of pending invalidations */

219

val invalidationCount: Int

220

}

221

```

222

223

### Composition Creation

224

225

Functions for creating new composition instances.

226

227

```kotlin { .api }

228

/**

229

* Creates a new Composition

230

* @param applier The applier that will receive composition changes

231

* @param parent Parent CompositionContext for hierarchical compositions

232

* @return New Composition instance

233

*/

234

fun Composition(

235

applier: Applier<*>,

236

parent: CompositionContext? = null

237

): ControlledComposition

238

239

/**

240

* Creates a new Composition with additional configuration

241

* @param applier The applier that will receive composition changes

242

* @param parent Parent CompositionContext for hierarchical compositions

243

* @param onDispose Callback invoked when composition is disposed

244

* @return New Composition instance

245

*/

246

fun Composition(

247

applier: Applier<*>,

248

parent: CompositionContext? = null,

249

onDispose: (() -> Unit)? = null

250

): ControlledComposition

251

```

252

253

### Applier Interface

254

255

Interface for applying composition changes to a tree structure.

256

257

```kotlin { .api }

258

/**

259

* Applies composition changes to a tree of nodes

260

* @param Node The type of nodes in the tree

261

*/

262

interface Applier<Node> {

263

/** The current node being modified */

264

val current: Node

265

266

/** Insert nodes at the specified index in the current node */

267

fun insertTopDown(index: Int, instance: Node)

268

269

/** Insert nodes from bottom up */

270

fun insertBottomUp(index: Int, instance: Node)

271

272

/** Remove nodes starting at index */

273

fun remove(index: Int, count: Int)

274

275

/** Move nodes from one position to another */

276

fun move(from: Int, to: Int, count: Int)

277

278

/** Clear all child nodes */

279

fun clear()

280

281

/** Move down to a child node */

282

fun down(node: Node)

283

284

/** Move up to the parent node */

285

fun up()

286

}

287

```

288

289

## Advanced Composition

290

291

### Recomposition Optimization

292

293

```kotlin { .api }

294

/**

295

* Information about recomposition for debugging and optimization

296

*/

297

interface RecompositionInfo {

298

/** Number of times this scope has recomposed */

299

val recomposeCount: Int

300

301

/** Number of times this scope has been skipped */

302

val skipCount: Int

303

}

304

305

/**

306

* Gets recomposition information for the current scope

307

* @return RecompositionInfo for debugging

308

*/

309

@Composable

310

fun currentRecompositionInfo(): RecompositionInfo

311

```

312

313

### Composition Debugging

314

315

```kotlin { .api }

316

/**

317

* Provides debugging information about the current composition

318

*/

319

object CompositionTracing {

320

/** Whether composition tracing is enabled */

321

var isEnabled: Boolean

322

323

/** Begin tracing a composition section */

324

fun beginSection(name: String)

325

326

/** End the current composition section */

327

fun endSection()

328

}

329

```

330

331

## iOS Platform Integration

332

333

### UIKit Integration

334

335

```kotlin { .api }

336

/**

337

* Creates a UIViewController that hosts Compose content

338

* @param content The composable content to display

339

* @return UIViewController containing the Compose UI

340

*/

341

fun ComposeUIViewController(content: @Composable () -> Unit): UIViewController

342

343

/**

344

* Platform-specific composition context for iOS

345

*/

346

class IOSCompositionContext : CompositionContext {

347

/** The UIView hosting the composition */

348

val hostView: UIView

349

350

/** Main thread dispatcher for iOS */

351

val mainDispatcher: CoroutineDispatcher

352

}

353

```

354

355

## Performance Considerations

356

357

- **Remember Keys**: Use appropriate keys to control when values are recalculated

358

- **Composition Scoping**: Keep composable functions focused and avoid large composition trees

359

- **State Hoisting**: Hoist state only when necessary to minimize recomposition scope

360

- **Skippable Composables**: Design composables to be skippable by avoiding reading state unnecessarily

361

- **Composition Debugging**: Use composition tracing to identify performance bottlenecks