# CompositionObserver

Artifact: [androidx.compose.runtime:runtime](https://developer.android.com/jetpack/androidx/releases/compose-runtime) [View Source](https://cs.android.com/search?q=file:androidx/compose/runtime/tooling/CompositionObserver.kt+class:androidx.compose.runtime.tooling.CompositionObserver) Added in [1.6.0](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.6.0) Common/AllAndroid/JVM
- Cmn

  ```
  @ExperimentalComposeRuntimeApi
  interface CompositionObserver
  ```

*** ** * ** ***

Observe `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope` management inside composition.

The expected lifecycle of a `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope` in composition is as follows:

```kotlin
// In the composition phase:
[onBeginComposition]
       ┃
[onScopeEnter] ━┓   // Composition enters a scope
                ┃
         [onReadInScope]  // Record reads inside the scope
                ┃
                ┗━ [onScopeEnter]
                    ...             // Potentially enter nested function scopes
                ┏━ [onScopeExit]
                ┃
[onScopeExit]  ━┛   // Composition leaves the scope
       ┃
[onEndComposition]

// In the apply changes phase:
[onScopeDisposed]   // Scope is discarded by composition and is no longer used.
```

The scopes can be invalidated at any point either by values previously reported in `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onReadInScope(androidx.compose.runtime.RecomposeScope,kotlin.Any)` or by calling `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope#invalidate()` directly. In these cases, `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeInvalidated(androidx.compose.runtime.RecomposeScope,kotlin.Any)` will be called with the associated instance or `null` if the scope was invalidated directly.

Note that invalidation of the scope does not guarantee it will be composed. Some cases where it is not composed are:

1. The scope is no longer part of the composition (e.g the parent scope no longer executed the code branch the scope was a part of)

2. The scope is part of movable content that was moved out of the composition.

In the case of movable content, the scope will be recomposed as part of a different composition when it is moved to that composition or it might be discarded (with a corresponding `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeDisposed(androidx.compose.runtime.RecomposeScope)` call) if no other composition claims it.

## Summary

| ### Public functions |
|---|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onBeginComposition(androidx.compose.runtime.tooling.ObservableComposition)(composition: https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/ObservableComposition)` Called when the composition process begins for `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onBeginComposition(androidx.compose.runtime.tooling.ObservableComposition)` instance. | Cmn |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onEndComposition(androidx.compose.runtime.tooling.ObservableComposition)(composition: https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/ObservableComposition)` Called after composition process has been completed for `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onEndComposition(androidx.compose.runtime.tooling.ObservableComposition)`. | Cmn |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onReadInScope(androidx.compose.runtime.RecomposeScope,kotlin.Any)(scope: https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope, value: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-any/index.html)` Called when read of `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onReadInScope(androidx.compose.runtime.RecomposeScope,kotlin.Any)` is recorded in `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onReadInScope(androidx.compose.runtime.RecomposeScope,kotlin.Any)` during composition. | Cmn |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeDisposed(androidx.compose.runtime.RecomposeScope)(scope: https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope)` Called when `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope` is no longer used in composition. | Cmn |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeEnter(androidx.compose.runtime.RecomposeScope)(scope: https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope)` Called when `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeEnter(androidx.compose.runtime.RecomposeScope)` enters the composition. | Cmn |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeExit(androidx.compose.runtime.RecomposeScope)(scope: https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope)` Called when `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope` exits composition. | Cmn |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeInvalidated(androidx.compose.runtime.RecomposeScope,kotlin.Any)(scope: https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope, value: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-any/index.html?)` Called when `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeInvalidated(androidx.compose.runtime.RecomposeScope,kotlin.Any)` is invalidated by composition or `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope#invalidate()` call. | Cmn |

## Public functions

### onBeginComposition

Cmn Added in [1.9.0](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.9.0)

```
fun onBeginComposition(composition: ObservableComposition): Unit
```

Called when the composition process begins for `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onBeginComposition(androidx.compose.runtime.tooling.ObservableComposition)` instance.

### onEndComposition

Cmn Added in [1.9.0](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.9.0)

```
fun onEndComposition(composition: ObservableComposition): Unit
```

Called after composition process has been completed for `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onEndComposition(androidx.compose.runtime.tooling.ObservableComposition)`.

### onReadInScope

Cmn Added in [1.9.0](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.9.0)

```
fun onReadInScope(scope: RecomposeScope, value: Any): Unit
```

Called when read of `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onReadInScope(androidx.compose.runtime.RecomposeScope,kotlin.Any)` is recorded in `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onReadInScope(androidx.compose.runtime.RecomposeScope,kotlin.Any)` during composition.

Reads can be recorded without re-execution of the function associated with the scope, for example when derived state invalidates the scope with the same value as before.

The instances passed to this method are only tracked between `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeEnter(androidx.compose.runtime.RecomposeScope)` and `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeExit(androidx.compose.runtime.RecomposeScope)` calls. Previously recorded instances should also be cleared when `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeEnter(androidx.compose.runtime.RecomposeScope)` is called again, to avoid keeping stale instances that are no longer tracked by composition. For example, this happens with `remember { state.value }`, with `state` recorded only during first composition.

| Parameters |
|---|---|
| `scope: https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope` | A `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope` that the read occurred in. |
| `value: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-any/index.html` | A value that was recorded in `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onReadInScope(androidx.compose.runtime.RecomposeScope,kotlin.Any)` and can invalidate it in the future. In most cases, `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onReadInScope(androidx.compose.runtime.RecomposeScope,kotlin.Any)` is a snapshot state instance. |

### onScopeDisposed

Cmn Added in [1.9.0](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.9.0)

```
fun onScopeDisposed(scope: RecomposeScope): Unit
```

Called when `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope` is no longer used in composition. Can be called from any thread whenever composition applies changes or is disposed.

### onScopeEnter

Cmn Added in [1.9.0](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.9.0)

```
fun onScopeEnter(scope: RecomposeScope): Unit
```

Called when `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeEnter(androidx.compose.runtime.RecomposeScope)` enters the composition.

### onScopeExit

Cmn Added in [1.9.0](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.9.0)

```
fun onScopeExit(scope: RecomposeScope): Unit
```

Called when `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope` exits composition.

### onScopeInvalidated

Cmn Added in [1.9.0](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.9.0)

```
fun onScopeInvalidated(scope: RecomposeScope, value: Any?): Unit
```

Called when `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeInvalidated(androidx.compose.runtime.RecomposeScope,kotlin.Any)` is invalidated by composition or `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope#invalidate()` call.

Note that for invalidations caused by a state change, this callback is not called immediately on the state write. Usually, invalidations from state changes are recorded right before recomposition starts or during composition (e.g. if `rememberUpdatedState` is used). This method is always guaranteed to be called before `https://developer.android.com/reference/kotlin/androidx/compose/runtime/tooling/CompositionObserver#onScopeEnter(androidx.compose.runtime.RecomposeScope)` for the corresponding invalidation is executed. If the scope was invalidated by `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope#invalidate()`, however, this callback is executed before `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope#invalidate()` returns.

| Parameters |
|---|---|
| `scope: https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope` | A `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope` that is invalidated. |
| `value: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-any/index.html?` | A value that invalidated composition. Can be `null` if the scope was invalidated by calling `https://developer.android.com/reference/kotlin/androidx/compose/runtime/RecomposeScope#invalidate()` directly. |