{% setvar book_path %}/reference/androidx/_book.yaml{% endsetvar %} {% include "_shared/_reference-head-tags.html" %}

Snapshot

public sealed class Snapshot

Known direct subclasses
MutableSnapshot

A snapshot of the values return by mutable states and other state objects.


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.

See also
takeSnapshot
takeMutableSnapshot
mutableStateOf
mutableStateListOf
mutableStateMapOf

Summary

Nested types

public static class Snapshot.Companion

Protected constructors

Snapshot(int id, @NonNull SnapshotIdSet invalid)

Public methods

void

Dispose the snapshot.

final @NonNull T
<T extends Object> enter(@NonNull Function0<@NonNull T> block)

Enter the snapshot.

int

The snapshot id of the snapshot.

abstract boolean

True if any change to a state object in this snapshot will throw.

abstract @NonNull Snapshot

The root snapshot for this snapshot.

abstract boolean

Whether there are any pending changes in this snapshot.

abstract @NonNull Snapshot
takeNestedSnapshot(Function1<@NonNull ObjectUnit> readObserver)

Take a snapshot of the state values in this snapshot.

final Snapshot

Enter the snapshot, returning the previous Snapshot for leaving this snapshot later using unsafeLeave.

final void

Leave the snapshot, restoring the oldSnapshot before returning.

Extension functions

final @NonNull SnapshotContextElement

Return a SnapshotContextElement that will enter this Snapshot whenever the associated coroutine is resumed and leave this snapshot when it suspends.

Protected constructors

Snapshot

protected Snapshot(int id, @NonNull SnapshotIdSet invalid)

Public methods

dispose

public void 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.

enter

public final @NonNull T <T extends Object> enter(@NonNull Function0<@NonNull T> block)

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.

getId

public int getId()

The snapshot id of the snapshot. This is a unique number from a monotonically increasing value for each snapshot taken.

getReadOnly

public abstract boolean getReadOnly()

True if any change to a state object in this snapshot will throw.

getRoot

public abstract @NonNull Snapshot getRoot()

The root snapshot for this snapshot. For non-nested snapshots this is always this. For nested snapshot it is the parent's root.

hasPendingChanges

public abstract boolean hasPendingChanges()

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

takeNestedSnapshot

public abstract @NonNull Snapshot takeNestedSnapshot(Function1<@NonNull ObjectUnit> readObserver)

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.

unsafeEnter

@ExperimentalComposeApi
public final Snapshot unsafeEnter()

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.

unsafeLeave

@ExperimentalComposeApi
public final void unsafeLeave(Snapshot oldSnapshot)

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

Extension functions

SnapshotContextElementKt.asContextElement

@ExperimentalComposeApi
public final @NonNull SnapshotContextElement SnapshotContextElementKt.asContextElement(@NonNull Snapshot receiver)

Return a SnapshotContextElement that will enter this Snapshot whenever the associated coroutine is resumed and leave this snapshot when it suspends. The snapshot still must be disposed separately when it will no longer be used.

import androidx.compose.runtime.snapshots.Snapshot
import androidx.compose.runtime.snapshots.asContextElement

runBlocking {
    val snapshot = Snapshot.takeSnapshot()
    try {
        withContext(snapshot.asContextElement()) {
            // Data observed by separately reading stateA and stateB are consistent with
            // the snapshot context element across suspensions
            doSomethingSuspending(someObject.stateA)
            doSomethingSuspending(someObject.stateB)
        }
    } finally {
        // Snapshot must be disposed after it will not be used again
        snapshot.dispose()
    }
}