ComposerLite

class ComposerLite(slotTable: SlotTable = SlotTable(), invalidationQueue: InvalidationQueue = InvalidationQueue(), warningLogger: (String) -> Unit? = null, onInvalidated: () -> Unit? = null, localSnapshotInspector: (Any?) -> List<CompositionLocalDiagnostic>? = null, sourceCallSiteCollector: () -> List<CompositionSourceCallSite>? = null)(source)

Coordinates transactional, group-based incremental composition without compiler-generated flags.

runGroup builds a positional scope tree in slotTable. A committed group result is reused when its explicit inputs are equal and none of its observed state has invalidated the scope. State invalidations are coalesced in invalidationQueue. Composition runs in a pinned read Snapshot and prepareRoot lets a host commit or roll back runtime changes together with another mutable tree.

Composer instances are thread-confined. Calls that compose, commit, abort, run effects, or dispose an instance MUST be serialized by its owner.

Parameters

slotTable

scope/slot tree owned by this composer

invalidationQueue

queue that coalesces state-driven scope invalidations

warningLogger

optional sink for structural-drift warnings, emitted once per drift location

onInvalidated

optional callback invoked when a clean scope first becomes dirty; repeated invalidations before the next composition are coalesced

localSnapshotInspector

optional formatter for opaque local snapshots included in diagnostics

sourceCallSiteCollector

optional collector invoked only when a new scope is created

Samples

val count = mutableStateOf(0)
val committedValues = mutableListOf<String>()
val composer = ComposerLite()

fun compose(): String = composer.composeRoot {
    composer.runGroup(signature = "counter") { _ ->
        val prefix = composer.remember(keys = emptyList()) { "Count" }
        "$prefix: ${count.value}".also { value ->
            composer.sideEffect { committedValues += value }
        }
    }
}

check(compose() == "Count: 0")
composer.commitSideEffects()
count.value = 1
check(composer.hasPendingInvalidations())
check(compose() == "Count: 1")
composer.commitSideEffects()
check(committedValues == listOf("Count: 0", "Count: 1"))

composer.dispose()

Constructors

Link copied to clipboard
constructor(slotTable: SlotTable = SlotTable(), invalidationQueue: InvalidationQueue = InvalidationQueue(), warningLogger: (String) -> Unit? = null, onInvalidated: () -> Unit? = null, localSnapshotInspector: (Any?) -> List<CompositionLocalDiagnostic>? = null, sourceCallSiteCollector: () -> List<CompositionSourceCallSite>? = null)

Types

Link copied to clipboard

Owns one candidate composition transaction until it is committed or aborted.

Functions

Link copied to clipboard

Runs all effect operations queued by committed compositions.

Link copied to clipboard
fun <T> composeRoot(block: () -> T): T

Composes block, commits the runtime transaction, and returns its candidate value.

Link copied to clipboard
fun disposableEffect(keys: List<Any?>, effect: () -> () -> Unit?)

Registers a keyed effect in the next positional effect slot of the current scope.

Link copied to clipboard
fun dispose()

Disposes every scope, observation, remembered value, active effect, and pending operation.

Link copied to clipboard

Removes and returns queued state invalidations after ancestor compaction.

Link copied to clipboard

Returns whether state-driven scope invalidations are waiting in the queue.

Link copied to clipboard

Returns a deterministic key for the next positional saveable slot in the current scope.

Link copied to clipboard
fun <T> prepareRoot(collectDiagnostics: Boolean = false, block: () -> T): ComposerLite.PreparedComposition<T>

Composes a candidate root result without finalizing scope, observation, or effect changes.

Link copied to clipboard
fun <T> remember(keys: List<Any?>, calculation: () -> T): T

Returns a value retained in the next positional remember slot of the current scope.

Link copied to clipboard

Marks the root dirty for the next composition attempt.

Link copied to clipboard
fun <T> runGroup(signature: Any, inputs: Any? = RecomposeScope.NoInputs, reuseResult: (previous: T, next: T) -> Boolean? = null, block: (RecomposeScope) -> T): T

Runs or reuses one positional group in the current composition scope.

Link copied to clipboard
fun sideEffect(effect: () -> Unit)

Registers effect to run once after the current composition commits.

Link copied to clipboard
fun <T> withKeys(keys: List<Any?>, block: () -> T): T

Runs block with keys appended to the current positional-key namespace.