# SnapshotMutationPolicy

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/SnapshotMutationPolicy.kt+class:androidx.compose.runtime.SnapshotMutationPolicy) Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.0.0) Common/AllAndroid/JVMNative/C/iOSJavaScript
- Cmn

  ```
  interface SnapshotMutationPolicy<T : Any?>
  ```

*** ** * ** ***

A policy to control how the result of `https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#mutableStateOf(kotlin.Any,androidx.compose.runtime.SnapshotMutationPolicy)` report and merge changes to the state object.

A mutation policy can be passed as an parameter to `https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#mutableStateOf(kotlin.Any,androidx.compose.runtime.SnapshotMutationPolicy)`, and `https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#compositionLocalOf(androidx.compose.runtime.SnapshotMutationPolicy,kotlin.Function0)`.

Typically, one of the stock policies should be used such as `https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#referentialEqualityPolicy()`, `https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#structuralEqualityPolicy()`, or `https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#neverEqualPolicy()`. However, a custom mutation policy can be created by implementing this interface, such as a counter policy,

```kotlin
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.SnapshotMutationPolicy
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.snapshots.Snapshot

/**
 * A policy that treats an `MutableState<Int>` as a counter. Changing the value to the same
 * integer value will not be considered a change. When snapshots are applied the changes made by
 * the applying snapshot are added together with changes of other snapshots. Changes to a
 * [MutableState] with a counterPolicy will never cause an apply conflict.
 *
 * As the name implies, this is useful when counting things, such as tracking the amount of a
 * resource consumed or produced while in a snapshot. For example, if snapshot A produces 10
 * things and snapshot B produces 20 things, the result of applying both A and B should be that
 * 30 things were produced.
 */
fun counterPolicy(): SnapshotMutationPolicy<Int> =
    object : SnapshotMutationPolicy<Int> {
        override fun equivalent(a: Int, b: Int): Boolean = a == b

        override fun merge(previous: Int, current: Int, applied: Int) =
            current + (applied - previous)
    }

val state = mutableStateOf(0, counterPolicy())
val snapshot1 = Snapshot.takeMutableSnapshot()
val snapshot2 = Snapshot.takeMutableSnapshot()
try {
    snapshot1.enter { state.value += 10 }
    snapshot2.enter { state.value += 20 }
    snapshot1.apply().check()
    snapshot2.apply().check()
} finally {
    snapshot1.dispose()
    snapshot2.dispose()
}

// State is now equals 30 as the changes made in the snapshots are added together.
```

## Summary

| ### Public functions |
|---|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/runtime/SnapshotMutationPolicy#equivalent(kotlin.Any,kotlin.Any)(a: T, b: T)` Determine if setting a state value's are equivalent and should be treated as equal. | Cmn |
| `open T?` | `https://developer.android.com/reference/kotlin/androidx/compose/runtime/SnapshotMutationPolicy#merge(kotlin.Any,kotlin.Any,kotlin.Any)(previous: T, current: T, applied: T)` Merge conflicting changes in snapshots. | Cmn |

## Public functions

### equivalent

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

```
fun equivalent(a: T, b: T): Boolean
```

Determine if setting a state value's are equivalent and should be treated as equal. If `https://developer.android.com/reference/kotlin/androidx/compose/runtime/SnapshotMutationPolicy#equivalent(kotlin.Any,kotlin.Any)` returns `true` the new value is not considered a change.

### merge

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

```
open fun merge(previous: T, current: T, applied: T): T?
```

Merge conflicting changes in snapshots. This is only called if `https://developer.android.com/reference/kotlin/androidx/compose/runtime/SnapshotMutationPolicy#merge(kotlin.Any,kotlin.Any,kotlin.Any)` and `https://developer.android.com/reference/kotlin/androidx/compose/runtime/SnapshotMutationPolicy#merge(kotlin.Any,kotlin.Any,kotlin.Any)` are not `https://developer.android.com/reference/kotlin/androidx/compose/runtime/SnapshotMutationPolicy#equivalent(kotlin.Any,kotlin.Any)`. If a valid merged value can be calculated then it should be returned.

For example, if the state object holds an immutable data class with multiple fields, and `https://developer.android.com/reference/kotlin/androidx/compose/runtime/SnapshotMutationPolicy#merge(kotlin.Any,kotlin.Any,kotlin.Any)` has changed fields that are unmodified by `https://developer.android.com/reference/kotlin/androidx/compose/runtime/SnapshotMutationPolicy#merge(kotlin.Any,kotlin.Any,kotlin.Any)` it might be valid to return a new copy of the data class that combines that changes from both `https://developer.android.com/reference/kotlin/androidx/compose/runtime/SnapshotMutationPolicy#merge(kotlin.Any,kotlin.Any,kotlin.Any)` and `https://developer.android.com/reference/kotlin/androidx/compose/runtime/SnapshotMutationPolicy#merge(kotlin.Any,kotlin.Any,kotlin.Any)` allowing a snapshot to apply that would have otherwise failed.

```kotlin
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.SnapshotMutationPolicy
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.snapshots.Snapshot

/**
 * A policy that treats an `MutableState<Int>` as a counter. Changing the value to the same
 * integer value will not be considered a change. When snapshots are applied the changes made by
 * the applying snapshot are added together with changes of other snapshots. Changes to a
 * [MutableState] with a counterPolicy will never cause an apply conflict.
 *
 * As the name implies, this is useful when counting things, such as tracking the amount of a
 * resource consumed or produced while in a snapshot. For example, if snapshot A produces 10
 * things and snapshot B produces 20 things, the result of applying both A and B should be that
 * 30 things were produced.
 */
fun counterPolicy(): SnapshotMutationPolicy<Int> =
    object : SnapshotMutationPolicy<Int> {
        override fun equivalent(a: Int, b: Int): Boolean = a == b

        override fun merge(previous: Int, current: Int, applied: Int) =
            current + (applied - previous)
    }

val state = mutableStateOf(0, counterPolicy())
val snapshot1 = Snapshot.takeMutableSnapshot()
val snapshot2 = Snapshot.takeMutableSnapshot()
try {
    snapshot1.enter { state.value += 10 }
    snapshot2.enter { state.value += 20 }
    snapshot1.apply().check()
    snapshot2.apply().check()
} finally {
    snapshot1.dispose()
    snapshot2.dispose()
}

// State is now equals 30 as the changes made in the snapshots are added together.
```