All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.dev.stateholder.StateHolder.kt Maven / Gradle / Ivy

Go to download

A simple library for managing state in Kotlin Multiplatform projects, using Kotlin Coroutines and `StateFlow`.

There is a newer version: 1.2.0
Show newest version
package dev.stateholder

import dev.stateholder.internal.DefaultStateHolder
import kotlin.reflect.KProperty
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow

/**
 * A container for managing state.
 *
 * The [state] property is the only property that should be exposed to the UI level. All updating
 * should be handled separately.
 *
 * Example usage:
 *
 *
 *
 * @param[State] The type of the state.
 */
public interface StateHolder {

    /**
     * The current state of type [State] exposed as a [StateFlow].
     */
    public val state: StateFlow

    /**
     * Add a source of state from another [Flow].
     *
     * This is useful when you need to update the [state] based off of another [Flow]. The [flow]
     * will be collected and [block] will be invoked in order to map the [T] value from [flow] to
     * the [State] value.
     *
     * The collecting can be stopped by cancelling the returned [Job].
     *
     * @param[T] The type of the value from flow.
     * @param[flow] The flow to collect from and update state with.
     * @param[scope] The scope to use for collecting the flow.
     * @param[block] The function to map the [T] value from [flow] to the [State] value.
     * @return The [Job] of the collection.
     */
    public fun  addSource(
        flow: Flow,
        scope: CoroutineScope,
        block: suspend (State, T) -> State,
    ): Job

    /**
     * Updates the MutableStateFlow.value atomically using the specified function of its value.
     * function may be evaluated multiple times, if value is being concurrently updated.
     */
    public fun update(block: (State) -> State)

    /**
     * Allows using delegation to access the [StateHolder.state] property.
     *
     * Example:
     *
     * ```
     * val state: StateFlow by stateContainer
     * ```
     */
    public operator fun getValue(
        stateOwner: StateOwner,
        property: KProperty<*>,
    ): StateFlow = state

    public companion object {

        /**
         * Create a [StateHolder] with the given [initialStateProvider].
         */
        internal fun  create(
            initialStateProvider: StateProvider,
        ): StateHolder = DefaultStateHolder(initialStateProvider)
    }
}

/**
 * Create a [StateHolder] with the given [initialStateProvider].
 *
 * @see [StateHolder]
 */
public fun  stateContainer(
    initialStateProvider: StateProvider,
): StateHolder = StateHolder.create(initialStateProvider)

/**
 * Create a [StateHolder] with the given [initialState].
 *
 * @see [StateHolder]
 */
public fun  stateContainer(
    initialState: State,
): StateHolder = StateHolder.create(provideState(initialState))

public fun  Flow.collectToState(
    container: StateHolder,
    scope: CoroutineScope,
    block: suspend (state: State, value: T) -> State,
): Job {
    return container.addSource(this, scope, block)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy