compositionLocalWithComputedDefaultOf

Function

Common
public fun <T> compositionLocalWithComputedDefaultOf(
    defaultComputation: CompositionLocalAccessorScope.() -> T
): ProvidableCompositionLocal<T>

Create a CompositionLocal that behaves like it was provided using ProvidableCompositionLocal.providesComputed by default. If a value is provided using ProvidableCompositionLocal.provides it behaves as if the CompositionLocal was produced by calling compositionLocalOf.

In other words, a CompositionLocal produced by can be provided identically to CompositionLocal created with compositionLocalOf with the only difference is how it behaves when the value is not provided. For a compositionLocalOf the default value is returned. If no default value has be computed for CompositionLocal the default computation is called.

The lambda passed to compositionLocalWithComputedDefaultOf will be invoked every time the CompositionLocal.current is evaluated for the composition local and computes its value based on the current value of the locals referenced in the lambda at the time CompositionLocal.current is evaluated. This allows providing values that can be derived from other locals. For example, if accent colors can be calculated from a single base color, the accent colors can be provided as computed composition locals. Providing a new base color would automatically update all the accent colors.

Parameters

defaultComputationthe default computation to use when this CompositionLocal is not provided.

Code Examples

compositionLocalComputedByDefault

fun compositionLocalComputedByDefault() {
    val LocalBaseValue = compositionLocalOf { 10 }
    val LocalLargerValue = compositionLocalWithComputedDefaultOf {
        LocalBaseValue.currentValue + 10
    }
}

compositionLocalComputedAfterProvidingLocal

fun compositionLocalComputedAfterProvidingLocal() {
    val LocalValue = compositionLocalOf { 10 }
    val LocalLargerValue = compositionLocalOf { 12 }
    val LocalComputedValue = compositionLocalWithComputedDefaultOf { LocalValue.currentValue + 4 }
    // In this example `LocalLargerValue` needs to be re-provided
    // whenever `LocalValue` is provided to keep its value larger
    // then `LocalValue`. However, `LocalComputedValue` does not
    // need to be re-provided to stay larger than `LocalValue` as
    // it is calculated based on the currently provided value for
    // `LocalValue`. Whenever `LocalValue` is provided the value
    // of `LocalComputedValue` is computed based on the currently
    // provided value for `LocalValue`.
    @Composable
    fun App() {
        // Value is 10, the default value for LocalValue
        val value = LocalValue.current
        // Value is 12, the default value
        val largerValue = LocalLargerValue.current
        // Value is computed to be 14
        val computedValue = LocalComputedValue.current
        CompositionLocalProvider(LocalValue provides 20) {
            // Value is 20 provided above
            val nestedValue = LocalValue.current
            // Value is still 12 as an updated value was not re-provided
            val nestedLargerValue = LocalLargerValue.current
            // Values is computed to be 24; LocalValue.current + 4
            val nestedComputedValue = LocalComputedValue.current
            CompositionLocalProvider(LocalLargerValue provides LocalValue.current + 2) {
                // Value is 22 provided above
                val newLargerValue = LocalLargerValue.current
                CompositionLocalProvider(LocalValue provides 50) {
                    // Value is now 50 provided above
                    val finalValue = LocalValue.current
                    // Value is still 22
                    val finalLargerValue = LocalLargerValue.current
                    // Value is now computed to be 54
                    val finalComputed = LocalComputedValue.current
                }
            }
        }
    }
}