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