---
title: "Snapshot"
description: "A snapshot of the values return by mutable states and other state objects. All state object will
have the same value in the snapshot as they had when the snapshot was created unless they are
explicitly changed in the snapshot.

To enter a snapshot call [enter]. The snapshot is the current snapshot as returned by
[currentSnapshot] until the control returns from the lambda (or until a nested [enter] is
called). All state objects will return the values associated with this snapshot, locally in the
thread, until [enter] returns. All other threads are unaffected.

Snapshots can be nested by calling [takeNestedSnapshot]."
type: "class"
---

<div class='type'>Class</div>


<a id='references'></a>

<div class='sourceset sourceset-common'>Common</div>


```kotlin
public sealed class Snapshot(
    snapshotId: SnapshotId,

    /** A set of all the snapshots that should be treated as invalid. */
    internal open var invalid: SnapshotIdSet,
)
```


A snapshot of the values return by mutable states and other state objects. All state object will
have the same value in the snapshot as they had when the snapshot was created unless they are
explicitly changed in the snapshot.

To enter a snapshot call `enter`. The snapshot is the current snapshot as returned by
`currentSnapshot` until the control returns from the lambda (or until a nested `enter` is
called). All state objects will return the values associated with this snapshot, locally in the
thread, until `enter` returns. All other threads are unaffected.

Snapshots can be nested by calling `takeNestedSnapshot`.


## Secondary Constructors

```kotlin
protected constructor(id: Int, invalid: SnapshotIdSet) : this(id.toSnapshotId(), invalid)
```

## Functions

```kotlin
public open fun dispose()
```


Dispose the snapshot. Neglecting to dispose a snapshot will result in difficult to diagnose
memory leaks as it indirectly causes all state objects to maintain its value for the
un-disposed snapshot.


```kotlin
public abstract fun takeNestedSnapshot(readObserver: ((Any) -> Unit)? = null): Snapshot
```


Take a snapshot of the state values in this snapshot. The resulting `Snapshot` is read-only.
All nested snapshots need to be disposed by calling `dispose` before resources associated
with this snapshot can be collected. Nested snapshots are still valid after the parent has
been disposed.


```kotlin
public abstract fun hasPendingChanges(): Boolean
```


Whether there are any pending changes in this snapshot. These changes are not visible until
the snapshot is applied.


```kotlin
public inline fun <T> enter(block: () -> T): T
```


Enter the snapshot. In `block` all state objects have the value associated with this
snapshot. The value of `currentSnapshot` will be this snapshot until this `block` returns or
a nested call to `enter` is called. When `block` returns, the previous current snapshot is
restored if there was one.

All changes to state objects inside `block` are isolated to this snapshot and are not visible
to other snapshot or as global state. If this is a `readOnly` snapshot, any changes to state
objects will throw an `IllegalStateException`.

For a `MutableSnapshot`, changes made to a snapshot inside `block` can be applied atomically
to the global state (or to its parent snapshot if it is a nested snapshot) by calling
`MutableSnapshot.apply`.


```kotlin
public fun unsafeEnter(): Snapshot?
```


Enter the snapshot, returning the previous `Snapshot` for leaving this snapshot later using
`unsafeLeave`. Prefer `enter` or `asContextElement` instead of using `unsafeEnter` directly
to prevent mismatched `unsafeEnter`/`unsafeLeave` calls.

After returning all state objects have the value associated with this snapshot. The value of
`currentSnapshot` will be this snapshot until `unsafeLeave` is called with the returned
`Snapshot` or another call to `unsafeEnter` or `enter` is made.

All changes to state objects until another snapshot is entered or this snapshot is left are
isolated to this snapshot and are not visible to other snapshot or as global state. If this
is a `readOnly` snapshot, any changes to state objects will throw an `IllegalStateException`.

For a `MutableSnapshot`, changes made to a snapshot can be applied atomically to the global
state (or to its parent snapshot if it is a nested snapshot) by calling
`MutableSnapshot.apply`.


```kotlin
public fun unsafeLeave(oldSnapshot: Snapshot?)
```


Leave the snapshot, restoring the `oldSnapshot` before returning. See `unsafeEnter`.


## Companion Object

#### Properties

<div class='sourceset sourceset-common'>Common</div>


```kotlin
public val current: Snapshot
```


Return the thread's active snapshot. If no thread snapshot is active then the current
global snapshot is used.



<div class='sourceset sourceset-common'>Common</div>


```kotlin
public val isInSnapshot: Boolean
```


Return `true` if the thread is currently in the context of a snapshot.



<div class='sourceset sourceset-common'>Common</div>


```kotlin
public val isApplyObserverNotificationPending: Boolean
```


Returns whether any threads are currently in the process of notifying observers about
changes to the global snapshot.



<div class='sourceset sourceset-common'>Common</div>


```kotlin
public const val PreexistingSnapshotId: Int
```


All new state objects initial state records should be `PreexistingSnapshotId` which then
allows snapshots outside the creating snapshot to access the object with its initial
state.



#### Methods

<div class='sourceset sourceset-common'>Common</div>


```kotlin
public fun takeSnapshot(readObserver: ((Any) -> Unit)? = null): Snapshot
```


Take a snapshot of the current value of all state objects. The values are preserved until
`Snapshot.dispose` is called on the result.

The `readObserver` parameter can be used to track when all state objects are read when in
`Snapshot.enter`. A snapshot apply observer can be registered using
`Snapshot.registerApplyObserver` to observe modification of state objects.

An active snapshot (after it is created but before `Snapshot.dispose` is called) requires
resources to track the values in the snapshot. Once a snapshot is no longer needed it
should disposed by calling `Snapshot.dispose`.

Leaving a snapshot active could cause hard to diagnose memory leaks values as are
maintained by state objects for these unneeded snapshots. Take care to always call
`Snapshot.dispose` on all snapshots when they are no longer needed.

Composition uses both of these to implicitly subscribe to changes to state object and
automatically update the composition when state objects read during composition change.

A nested snapshot can be taken of a snapshot which is an independent read-only copy of
the snapshot and can be disposed independently. This is used by `takeSnapshot` when in a
read-only snapshot for API consistency allowing the result of `takeSnapshot` to be
disposed leaving the parent snapshot active.

#### Parameters

| | |
| --- | --- |
| readObserver | called when any state object is read in the lambda passed to `Snapshot.enter` or in the `Snapshot.enter` of any nested snapshot. |




<div class='sourceset sourceset-common'>Common</div>


```kotlin
public fun takeMutableSnapshot(
            readObserver: ((Any) -> Unit)? = null,
            writeObserver: ((Any) -> Unit)? = null,
        ): MutableSnapshot
```


Take a snapshot of the current value of all state objects that also allows the state to
be changed and later atomically applied when `MutableSnapshot.apply` is called. The
values are preserved until `Snapshot.dispose` is called on the result. The global state
will either see all the changes made as one atomic change, when `MutableSnapshot .apply`
is called, or none of the changes if the mutable state object is disposed before being
applied.

The values in a snapshot can be modified by calling `Snapshot.enter` and then, in its
lambda, modify any state object. The new values of the state objects will only become
visible to the global state when `MutableSnapshot.apply` is called.

An active snapshot (after it is created but before `Snapshot.dispose` is called) requires
resources to track the values in the snapshot. Once a snapshot is no longer needed it
should disposed by calling `Snapshot.dispose`.

Leaving a snapshot active could cause hard to diagnose memory leaks as values are
maintained by state objects for these unneeded snapshots. Take care to always call
`Snapshot.dispose` on all snapshots when they are no longer needed.

A nested snapshot can be taken by calling `Snapshot.takeNestedSnapshot`, for a read-only
snapshot, or `MutableSnapshot.takeNestedMutableSnapshot` for a snapshot that can be
changed. Nested mutable snapshots are applied to the this, the parent snapshot, when
their `MutableSnapshot.apply` is called. Their applied changes will be visible to in this
snapshot but will not be visible other snapshots (including other nested snapshots) or
the global state until this snapshot is applied by calling `MutableSnapshot.apply`.

Once `MutableSnapshot.apply` is called on this, the parent snapshot, all calls to
`MutableSnapshot.apply` on an active nested snapshot will fail.

Changes to a mutable snapshot are isolated, using snapshot isolation, from all other
snapshots. Their changes are only visible as global state or to new snapshots once
`MutableSnapshot.apply` is called.

Applying a snapshot can fail if currently visible changes to the state object conflicts
with a change made in the snapshot.

When in a mutable snapshot, `takeMutableSnapshot` creates a nested snapshot of the
current mutable snapshot. If the current snapshot is read-only, an exception is thrown.
The current snapshot is the result of calling `currentSnapshot` which is updated by
calling `Snapshot.enter` which makes the `Snapshot` the current snapshot while in its
lambda.

Composition uses mutable snapshots to allow changes made in a `Composable` functions to
be temporarily isolated from the global state and is later applied to the global state
when the composition is applied. If `MutableSnapshot.apply` fails applying this snapshot,
the snapshot and the changes calculated during composition are disposed and a new
composition is scheduled to be calculated again.


Composition, layout and draw use `readObserver` to implicitly subscribe to changes to
state objects to know when to update.


Composition uses `writeObserver` to track when a state object is modified during
composition in order to invalidate the reads that have not yet occurred. This allows a
single pass of composition for state objects that are written to before they are read
(such as modifying the value of a dynamic ambient provider).

#### Parameters

| | |
| --- | --- |
| readObserver | called when any state object is read in the lambda passed to `Snapshot.enter` or in the `Snapshot.enter` of any nested snapshots. |
| writeObserver | called when a state object is created or just before it is written to the first time in the snapshot or a nested mutable snapshot. This might be called several times for the same object if nested mutable snapshots are created. |




<div class='sourceset sourceset-common'>Common</div>


```kotlin
public inline fun <T> global(block: () -> T): T
```


Escape the current snapshot, if there is one. All state objects will have the value
associated with the global while the `block` lambda is executing.

#### Returns

| | |
| --- | --- |
|  | the result of `block` |




<div class='sourceset sourceset-common'>Common</div>


```kotlin
public inline fun <R> withMutableSnapshot(block: () -> R): R
```


Take a `MutableSnapshot` and run `block` within it. When `block` returns successfully,
attempt to `MutableSnapshot.apply` the snapshot. Returns the result of `block` or throws
`SnapshotApplyConflictException` if snapshot changes attempted by `block` could not be
applied.

Prior to returning, any changes made to snapshot state (e.g. state holders returned by
`androidx.compose.runtime.mutableStateOf` are not visible to other threads. When
`withMutableSnapshot` returns successfully those changes will be made visible to other
threads and any snapshot observers (e.g. `androidx.compose.runtime.snapshotFlow`) will be
notified of changes.

`block` must not suspend if `withMutableSnapshot` is called from a suspend function.



<div class='sourceset sourceset-common'>Common</div>


```kotlin
public fun <T> observe(
            readObserver: ((Any) -> Unit)? = null,
            writeObserver: ((Any) -> Unit)? = null,
            block: () -> T,
        ): T
```


Observe reads and or write of state objects in the current thread.

This only affects the current snapshot (if any) and any new snapshots create from
`Snapshot.takeSnapshot` and `takeMutableSnapshot`. It will not affect any snapshots
previous created even if `Snapshot.enter` is called in `block`.

#### Parameters

| | |
| --- | --- |
| readObserver | called when any state object is read. |
| writeObserver | called when a state object is created or just before it is written to the first time in the snapshot or a nested mutable snapshot. This might be called several times for the same object if nested mutable snapshots are created. |
| block | the code the `readObserver` and `writeObserver` will be observing. Once `block` returns, the `readObserver` and `writeObserver` will no longer be called. |




<div class='sourceset sourceset-common'>Common</div>


```kotlin
public inline fun <T> withoutReadObservation(block: @DisallowComposableCalls () -> T): T
```


Passed `block` will be run with all the currently set snapshot read observers disabled.



<div class='sourceset sourceset-common'>Common</div>


```kotlin
public fun registerApplyObserver(observer: (Set<Any>, Snapshot) -> Unit): ObserverHandle
```


Register an apply listener that is called back when snapshots are applied to the global
state.

#### Returns

| | |
| --- | --- |
|  | `ObserverHandle` to unregister `observer`. |




<div class='sourceset sourceset-common'>Common</div>


```kotlin
public fun registerGlobalWriteObserver(observer: ((Any) -> Unit)): ObserverHandle
```


Register an observer of the first write to the global state of a global state object
since the last call to `sendApplyNotifications`.

Composition uses this to schedule a new composition whenever a state object that was read
in composition is modified.

State objects can be sent to the apply observer that have not been sent to global write
observers. This happens for state objects inside `MutableSnapshot` that is later applied
by calling `MutableSnapshot.apply`.

This should only be used to determine if a call to `sendApplyNotifications` should be
scheduled to be called.

#### Returns

| | |
| --- | --- |
|  | `ObserverHandle` to unregister `observer`. |




<div class='sourceset sourceset-common'>Common</div>


```kotlin
public fun notifyObjectsInitialized(): Unit
```


Notify the snapshot that all objects created in this snapshot to this point should be
considered initialized. If any state object is are modified passed this point it will
appear as modified in the snapshot and any applicable snapshot write observer will be
called for the object and the object will be part of the a set of mutated objects sent to
any applicable snapshot apply observer.

Unless `notifyObjectsInitialized` is called, state objects created in a snapshot are not
considered modified by the snapshot even if they are modified after construction.

Compose uses this between phases of composition to allow observing changes to state
objects create in a previous phase.



<div class='sourceset sourceset-common'>Common</div>


```kotlin
public fun sendApplyNotifications()
```


Send any pending apply notifications for state objects changed outside a snapshot.

Apply notifications for state objects modified outside snapshot are deferred until method
is called. This method is implicitly called whenever a non-nested `MutableSnapshot` is
applied making its changes visible to all new, non-nested snapshots.

Composition schedules this to be called after changes to state objects are detected an
observer registered with `registerGlobalWriteObserver`.



<div class='sourceset sourceset-common'>Common</div>


```kotlin
@InternalComposeApi public fun openSnapshotCount(): Int
```




