androidx.compose.runtime
In this page, you'll find documentation for types, properties, and functions available in the androidx.compose.runtime package. For example:
-
State APIs such as
State,remember,mutableStateOf, andcollectAsState. -
Side-effects APIs such as
LaunchedEffect, andSideEffect. -
Coroutines related APIs such as
rememberCoroutineScope, andsnapshotFlow. -
CompositionLocalAPIs such ascompositionLocalOf. -
Composition related APIs such as
Composition,Recomposer,ComposeNode, andRecomposeScope. -
Clock APIs such as
MonotonicFrameClock,withFrameMillis, -
Certain annotations such as
Composable, andStable.
If you're looking for guidance instead, check out the following Compose guides:
Interfaces
Applier |
An Applier is responsible for applying the tree-based operations that get emitted during a composition. |
Cmn
|
CancellationHandle |
Implementations of this interface can be used to cancel an ongoing operation or unregister a listener by calling |
Cmn
|
ComposeNodeLifecycleCallback |
Observes lifecycle of the node emitted with |
Cmn
|
Composer |
Composer is the interface that is targeted by the Compose Kotlin compiler plugin and used by code generation helpers. |
Cmn
|
Composition |
A composition object is usually constructed for you, and returned from an API that is used to initially compose a UI. |
Cmn
|
CompositionLocalAccessorScope |
Cmn
|
|
CompositionLocalMap |
A read-only, immutable snapshot of the |
Cmn
|
CompositionServiceKey |
A key to locate a service using the |
Cmn
|
CompositionServices |
Allows finding composition services from the runtime. |
Cmn
|
CompositionTracer |
Internal tracing API. |
Cmn
|
ControlledComposition |
A controlled composition is a |
Cmn
|
DisposableEffectResult |
Cmn
|
|
DoubleState |
A value holder where reads to the |
Cmn
|
FloatState |
A value holder where reads to the |
Cmn
|
IntState |
A value holder where reads to the |
Cmn
|
LongState |
A value holder where reads to the |
Cmn
|
MonotonicFrameClock |
Provides a time source for display frames and the ability to perform an action on the next frame. |
Cmn
|
MutableDoubleState |
A value holder where reads to the |
Cmn
|
MutableFloatState |
A value holder where reads to the |
Cmn
|
MutableIntState |
A value holder where reads to the |
Cmn
|
MutableLongState |
A value holder where reads to the |
Cmn
|
MutableState |
A mutable value holder where reads to the |
Cmn
|
PausableComposition |
A |
Cmn
|
PausedComposition |
|
Cmn
|
ProduceStateScope |
Receiver scope for use with |
Cmn
|
RecomposeScope |
Represents a recomposable scope or section of the composition hierarchy. |
Cmn
|
RecomposerInfo |
Read-only information about a |
Cmn
|
RememberObserver |
Objects implementing this interface are notified when they are initially used in a composition and when they are no longer being used. |
Cmn
|
ReusableComposition |
A |
Cmn
|
ScopeUpdateScope |
Internal compose compiler plugin API that is used to update the function the composer will call to recompose a recomposition scope. |
Cmn
|
ShouldPauseCallback |
The callback type used in |
Cmn
|
SnapshotMutationPolicy |
A policy to control how the result of |
Cmn
|
State |
A value holder where reads to the |
Cmn
|
Classes
AbstractApplier |
An abstract |
Cmn
|
BroadcastFrameClock |
A simple frame clock. |
Cmn
|
CompositeKeyHashCode |
The return type of |
Cmn
android
N
|
CompositionContext |
A |
Cmn
|
CompositionLocal |
Compose passes data through the composition tree explicitly through means of parameters to composable functions. |
Cmn
|
CompositionLocalContext |
Stores |
Cmn
|
DisposableEffectScope |
Receiver scope for |
Cmn
|
MovableContent |
This class is used internally by |
Cmn
|
MovableContentState |
A Compose compiler plugin API. |
Cmn
|
MovableContentStateReference |
A Compose compiler plugin API. |
Cmn
|
PausableMonotonicFrameClock |
A |
Cmn
|
ProvidableCompositionLocal |
A |
Cmn
|
ProvidedValue |
An instance to hold a value provided by |
Cmn
|
Recomposer |
The scheduler for performing recomposition and applying updates to one or more |
Cmn
|
SkippableUpdater |
Cmn
|
|
Updater |
A helper receiver scope class used by |
Cmn
|
Objects
Annotations
Composable |
|
Cmn
|
ComposableInferredTarget |
An annotation generated by the compose compiler plugin. |
Cmn
|
ComposableOpenTarget |
The |
Cmn
|
ComposableTarget |
The |
Cmn
|
ComposableTargetMarker |
This annotation is used to mark an annotation as being equivalent using |
Cmn
|
ComposeCompilerApi |
Cmn
|
|
DisallowComposableCalls |
This will prevent composable calls from happening inside of the function that it applies to. |
Cmn
|
DontMemoize |
Mark a lambda in composition to opt out of auto-memoization. |
Cmn
|
ExperimentalComposeApi |
Cmn
|
|
ExperimentalComposeRuntimeApi |
Cmn
|
|
ExplicitGroupsComposable |
This annotation can be applied to |
Cmn
|
Immutable |
|
Cmn
|
InternalComposeApi |
Cmn
|
|
InternalComposeTracingApi |
Cmn
|
|
NoLiveLiterals |
This annotation is used to indicate to the Compose Compiler to not attempt to generate live literals inside the scope of the declaration it is applied to, even when the live literals code generation is turned on. |
Cmn
|
NonRestartableComposable |
This annotation can be applied to |
Cmn
|
NonSkippableComposable |
This annotation can be applied to |
Cmn
|
ReadOnlyComposable |
This annotation can be applied to |
Cmn
|
Stable |
Stable is used to communicate some guarantees to the compose compiler about how a certain type or function will behave. |
Cmn
|
StableMarker |
|
Cmn
|
TestOnly |
Cmn
N
|
Enums
Recomposer.State |
Valid operational states of a |
Cmn
|
Type aliases
CheckResult |
This type alias is deprecated. It was never intended to be public |
Cmn
|
CompositeKeyHashCode |
android
N
|
Top-level functions summary
inline Unit |
@ComposableEmits a node into the composition of type |
Cmn
|
inline Unit |
@ComposableEmits a node into the composition of type |
Cmn
|
inline Unit |
@ComposableEmits a node into the composition of type |
Cmn
|
Composition |
Composition(applier: Applier<*>, parent: CompositionContext)This method is the way to initiate a composition. |
Cmn
|
Composition |
@ExperimentalComposeApiCreate a |
Cmn
|
Unit |
@Composable
|
Cmn
|
Unit |
@Composable
|
Cmn
|
Unit |
@Composable
|
Cmn
|
ControlledComposition |
@TestOnlyThis method is a way to initiate a composition. |
Cmn
|
ControlledComposition |
@TestOnly |
Cmn
|
Unit |
@ComposableThis function is deprecated. DisposableEffect must provide one or more 'key' parameters that define the identity of the DisposableEffect and determine when its previous effect should be disposed and a new effect started for the new key. |
Cmn
|
Unit |
@ComposableA side effect of composition that must run for any new unique value of |
Cmn
|
Unit |
@ComposableA side effect of composition that must run for any new unique value of |
Cmn
|
Unit |
@ComposableA side effect of composition that must run for any new unique value of |
Cmn
|
Unit |
@ComposableA side effect of composition that must run for any new unique value of |
Cmn
|
Unit |
@ComposableThis function is deprecated. LaunchedEffect must provide one or more 'key' parameters that define the identity of the LaunchedEffect and determine when its previous effect coroutine should be cancelled and a new effect launched for the new key. |
Cmn
|
Unit |
@ComposableWhen |
Cmn
|
Unit |
@ComposableWhen |
Cmn
|
Unit |
@ComposableWhen |
Cmn
|
Unit |
@ComposableWhen |
Cmn
|
PausableComposition |
PausableComposition(applier: Applier<*>, parent: CompositionContext)Create a |
Cmn
|
inline Unit |
@ComposableEmits a recyclable node into the composition of type |
Cmn
|
inline Unit |
@ComposableEmits a recyclable node into the composition of type |
Cmn
|
inline Unit |
@ComposableEmits a recyclable node into the composition of type |
Cmn
|
ReusableComposition |
ReusableComposition(applier: Applier<*>, parent: CompositionContext)This method is the way to initiate a reusable composition. |
Cmn
|
inline Unit |
@ComposableA utility function to mark a composition as supporting recycling. |
Cmn
|
inline Unit |
@ComposableAn optional utility function used when hosting |
Cmn
|
Unit |
@ComposableSchedule |
Cmn
|
Unit |
Clears current composition errors in hot reload mode. |
Cmn
|
ProvidableCompositionLocal<T> |
<T : Any?> compositionLocalOf(Create a |
Cmn
|
ProvidableCompositionLocal<T> |
<T : Any?> compositionLocalWithComputedDefaultOf(defaultComputation: CompositionLocalAccessorScope.() -> T)Create a |
Cmn
|
List<Pair<Exception, Boolean>> |
This function is deprecated. currentCompositionErrors only reports errors that extend from Exception. |
Cmn
|
State<T> |
@StateFactoryMarkerCreates a |
Cmn
|
State<T> |
@StateFactoryMarkerCreates a |
Cmn
|
Unit |
Disables hot reload mode in recomposer. |
Cmn
|
Unit |
Invalidates composed groups with the given key. |
Cmn
|
Boolean |
Internal tracing API. |
Cmn
|
inline T |
@Composable
|
Cmn
|
@Composable () -> Unit |
@RememberInCompositionConvert a lambda into one that moves the remembered state and nodes created in a previous call to the new location it is called. |
Cmn
|
@Composable (P) -> Unit |
@RememberInCompositionConvert a lambda into one that moves the remembered state and nodes created in a previous call to the new location it is called. |
Cmn
|
@Composable (P1, P2) -> Unit |
@RememberInCompositionConvert a lambda into one that moves the remembered state and nodes created in a previous call to the new location it is called. |
Cmn
|
@Composable (P1, P2, P3) -> Unit |
@RememberInCompositionConvert a lambda into one that moves the remembered state and nodes created in a previous call to the new location it is called. |
Cmn
|
@Composable (P1, P2, P3, P4) -> Unit |
@RememberInCompositionConvert a lambda into one that moves the remembered state and nodes created in a previous call to the new location it is called. |
Cmn
|
@Composable R.() -> Unit |
@RememberInCompositionConvert a lambda with a receiver into one that moves the remembered state and nodes created in a previous call to the new location it is called. |
Cmn
|
@Composable R.(P) -> Unit |
@RememberInCompositionConvert a lambda with a receiver into one that moves the remembered state and nodes created in a previous call to the new location it is called. |
Cmn
|
@Composable R.(P1, P2) -> Unit |
@RememberInCompositionConvert a lambda with a receiver into one that moves the remembered state and nodes created in a previous call to the new location it is called. |
Cmn
|
@Composable R.(P1, P2, P3) -> Unit |
@RememberInCompositionConvert a lambda with a receiver into one that moves the remembered state and nodes created in a previous call to the new location it is called. |
Cmn
|
MutableDoubleState |
Return a new |
Cmn
|
MutableFloatState |
Return a new |
Cmn
|
MutableIntState |
@StateFactoryMarkerReturn a new |
Cmn
|
MutableLongState |
@StateFactoryMarkerReturn a new |
Cmn
|
SnapshotStateList<T> |
@StateFactoryMarkerCreate a instance of |
Cmn
|
SnapshotStateList<T> |
@StateFactoryMarkerCreate an instance of |
Cmn
|
SnapshotStateMap<K, V> |
@StateFactoryMarkerCreate a instance of |
Cmn
|
SnapshotStateMap<K, V> |
@StateFactoryMarkerCreate a instance of |
Cmn
|
MutableState<T> |
@StateFactoryMarkerReturn a new |
Cmn
|
SnapshotStateSet<T> |
@StateFactoryMarkerCreate a instance of |
Cmn
|
SnapshotStateSet<T> |
@StateFactoryMarkerCreate an instance of |
Cmn
|
SnapshotMutationPolicy<T> |
<T : Any?> neverEqualPolicy()A policy never treat values of a |
Cmn
|
State<T> |
@ComposableReturn an observable |
Cmn
|
State<T> |
@ComposableReturn an observable |
Cmn
|
State<T> |
@ComposableReturn an observable |
Cmn
|
State<T> |
@ComposableReturn an observable |
Cmn
|
State<T> |
@ComposableReturn an observable |
Cmn
|
SnapshotMutationPolicy<T> |
<T : Any?> referentialEqualityPolicy()A policy to treat values of a |
Cmn
|
inline T |
@ComposableRemember the value produced by |
Cmn
|
inline T |
@ComposableRemember the value returned by |
Cmn
|
inline T |
@ComposableRemember the value returned by |
Cmn
|
inline T |
@ComposableRemember the value returned by |
Cmn
|
inline T |
@ComposableRemember the value returned by |
Cmn
|
CompositionContext |
An Effect to construct a |
Cmn
|
inline CoroutineScope |
@ComposableReturn a |
Cmn
|
State<T> |
@Composable
|
Cmn
|
Unit |
@TestOnlySimulates hot reload of all current compositions by disposing all composed content and restarting compositions. |
Cmn
|
Flow<T> |
<T : Any?> snapshotFlow(block: () -> T) |
Cmn
|
Unit |
@ComposeCompilerApiA Compose internal function. |
Cmn
|
Unit |
@ComposeCompilerApiA Compose internal function. |
Cmn
|
Unit |
@ComposeCompilerApiA Compose internal function. |
Cmn
|
ProvidableCompositionLocal<T> |
<T : Any?> staticCompositionLocalOf(defaultFactory: () -> T)Create a |
Cmn
|
SnapshotMutationPolicy<T> |
<T : Any?> structuralEqualityPolicy()A policy to treat values of a |
Cmn
|
Unit |
Internal tracing API. |
Cmn
|
Unit |
@ComposeCompilerApiInternal tracing API. |
Cmn
|
inline T |
@Composable
|
Cmn
|
inline T |
@Composable
|
Cmn
|
suspend R |
<R : Any?> withFrameMillis(onFrame: (frameTimeMillis: Long) -> R)Suspends until a new frame is requested, immediately invokes |
Cmn
|
suspend R |
<R : Any?> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R)Suspends until a new frame is requested, immediately invokes |
Cmn
|
suspend R |
<R : Any?> withRunningRecomposer(block: suspend CoroutineScope.(recomposer: Recomposer) -> R)Runs |
Cmn
|
Extension functions summary
DoubleState |
Converts a |
Cmn
|
FloatState |
Converts a |
Cmn
|
IntState |
State<Int>.asIntState()Converts a |
Cmn
|
LongState |
State<Long>.asLongState()Converts a |
Cmn
|
inline T |
@ComposeCompilerApiA Compose compiler plugin API. |
Cmn
|
State<T> |
@ComposableCollects values from this |
Cmn
|
State<R> |
@ComposableCollects values from this |
Cmn
|
inline operator Double |
DoubleState.getValue(thisObj: Any?, property: KProperty<*>)Permits property delegation of |
Cmn
|
inline operator Float |
FloatState.getValue(thisObj: Any?, property: KProperty<*>)Permits property delegation of |
Cmn
|
inline operator Int |
Permits property delegation of |
Cmn
|
inline operator Long |
Permits property delegation of |
Cmn
|
inline operator T |
Permits property delegation of |
Cmn
|
inline operator Unit |
MutableDoubleState.setValue(Permits property delegation of |
Cmn
|
inline operator Unit |
MutableFloatState.setValue(Permits property delegation of |
Cmn
|
inline operator Unit |
MutableIntState.setValue(thisObj: Any?, property: KProperty<*>, value: Int)Permits property delegation of |
Cmn
|
inline operator Unit |
MutableLongState.setValue(Permits property delegation of |
Cmn
|
inline operator Unit |
<T : Any?> MutableState<T>.setValue(Permits property delegation of |
Cmn
|
Long |
Converts a |
Cmn
|
inline Long |
android
N
|
|
SnapshotStateList<T> |
<T : Any?> Collection<T>.toMutableStateList()Create an instance of |
Cmn
|
SnapshotStateMap<K, V> |
<K : Any?, V : Any?> Iterable<Pair<K, V>>.toMutableStateMap()Create an instance of |
Cmn
|
String |
CompositeKeyHashCode.toString(radix: Int)Returns a String representation of a |
Cmn
|
inline String |
android
N
|
|
suspend inline R |
<R : Any?> MonotonicFrameClock.withFrameMillis(Suspends until a new frame is requested, immediately invokes |
Cmn
|
Top-level properties summary
MonotonicFrameClock |
This property is deprecated. MonotonicFrameClocks are not globally applicable across platforms. |
Cmn
android
N
JS
|
CompositeKeyHashCode |
An empty |
Cmn
android
N
|
Composer |
TODO(lmr): provide documentation |
Cmn
|
Int |
This property is deprecated. Prefer the higher-precision currentCompositeKeyHashCode |
Cmn
|
CompositeKeyHashCode |
A higher-precision variation of |
Cmn
|
CompositionContext |
Returns the |
Cmn
|
CompositionLocalContext |
Returns the current |
Cmn
|
RecomposeScope |
Returns an object which can be used to invalidate the current scope at this point in composition. |
Cmn
|
Extension properties summary
MonotonicFrameClock |
Returns the |
Cmn
|
CoroutineContext |
The |
Cmn
|
Top-level functions
ComposeNode
@Composable
inline fun <T : Any, E : Applier<*>> ComposeNode(
noinline factory: () -> T,
update: @DisallowComposableCalls Updater<T>.() -> Unit
): Unit
Emits a node into the composition of type T.
This function will throw a runtime exception if E is not a subtype of the applier of the currentComposer.
import androidx.compose.runtime.AbstractApplier import androidx.compose.runtime.Composable import androidx.compose.runtime.ComposeNode import androidx.compose.runtime.Composition import androidx.compose.runtime.CompositionContext import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember // Provided we have a tree with a node base type like the following abstract class Node { val children = mutableListOf<Node>() } // We would implement an Applier class like the following, which would teach compose how to // manage a tree of Nodes. class NodeApplier(root: Node) : AbstractApplier<Node>(root) { override fun insertTopDown(index: Int, instance: Node) { current.children.add(index, instance) } override fun insertBottomUp(index: Int, instance: Node) { // Ignored as the tree is built top-down. } override fun remove(index: Int, count: Int) { current.children.remove(index, count) } override fun move(from: Int, to: Int, count: Int) { current.children.move(from, to, count) } override fun onClear() { root.children.clear() } } // A function like the following could be created to create a composition provided a root Node. fun Node.setContent(parent: CompositionContext, content: @Composable () -> Unit): Composition { return Composition(NodeApplier(this), parent).apply { setContent(content) } } // assuming we have Node sub-classes like "TextNode" and "GroupNode" class TextNode : Node() { var text: String = "" var onClick: () -> Unit = {} } class GroupNode : Node() // Composable equivalents could be created @Composable fun Text(text: String, onClick: () -> Unit = {}) { ComposeNode<TextNode, NodeApplier>(::TextNode) { set(text) { this.text = it } set(onClick) { this.onClick = it } } } @Composable fun Group(content: @Composable () -> Unit) { ComposeNode<GroupNode, NodeApplier>(::GroupNode, {}, content) } // and then a sample tree could be composed: fun runApp(root: GroupNode, parent: CompositionContext) { root.setContent(parent) { var count by remember { mutableStateOf(0) } Group { Text("Count: $count") Text("Increment") { count++ } } } }
| Parameters | |
|---|---|
noinline factory: () -> T |
A function which will create a new instance of |
update: @DisallowComposableCalls Updater<T>.() -> Unit |
A function to perform updates on the node. This will run every time emit is executed. This function is called in place and will be inlined. |
| See also | |
|---|---|
Updater |
|
Applier |
|
Composition |
ComposeNode
@Composable
inline fun <T : Any?, E : Applier<*>> ComposeNode(
noinline factory: () -> T,
update: @DisallowComposableCalls Updater<T>.() -> Unit,
content: @Composable () -> Unit
): Unit
Emits a node into the composition of type T. Nodes emitted inside of content will become children of the emitted node.
This function will throw a runtime exception if E is not a subtype of the applier of the currentComposer.
import androidx.compose.runtime.AbstractApplier import androidx.compose.runtime.Composable import androidx.compose.runtime.ComposeNode import androidx.compose.runtime.Composition import androidx.compose.runtime.CompositionContext import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember // Provided we have a tree with a node base type like the following abstract class Node { val children = mutableListOf<Node>() } // We would implement an Applier class like the following, which would teach compose how to // manage a tree of Nodes. class NodeApplier(root: Node) : AbstractApplier<Node>(root) { override fun insertTopDown(index: Int, instance: Node) { current.children.add(index, instance) } override fun insertBottomUp(index: Int, instance: Node) { // Ignored as the tree is built top-down. } override fun remove(index: Int, count: Int) { current.children.remove(index, count) } override fun move(from: Int, to: Int, count: Int) { current.children.move(from, to, count) } override fun onClear() { root.children.clear() } } // A function like the following could be created to create a composition provided a root Node. fun Node.setContent(parent: CompositionContext, content: @Composable () -> Unit): Composition { return Composition(NodeApplier(this), parent).apply { setContent(content) } } // assuming we have Node sub-classes like "TextNode" and "GroupNode" class TextNode : Node() { var text: String = "" var onClick: () -> Unit = {} } class GroupNode : Node() // Composable equivalents could be created @Composable fun Text(text: String, onClick: () -> Unit = {}) { ComposeNode<TextNode, NodeApplier>(::TextNode) { set(text) { this.text = it } set(onClick) { this.onClick = it } } } @Composable fun Group(content: @Composable () -> Unit) { ComposeNode<GroupNode, NodeApplier>(::GroupNode, {}, content) } // and then a sample tree could be composed: fun runApp(root: GroupNode, parent: CompositionContext) { root.setContent(parent) { var count by remember { mutableStateOf(0) } Group { Text("Count: $count") Text("Increment") { count++ } } } }
| Parameters | |
|---|---|
noinline factory: () -> T |
A function which will create a new instance of |
update: @DisallowComposableCalls Updater<T>.() -> Unit |
A function to perform updates on the node. This will run every time emit is executed. This function is called in place and will be inlined. |
content: @Composable () -> Unit |
the composable content that will emit the "children" of this node. |
| See also | |
|---|---|
Updater |
|
Applier |
|
Composition |
ComposeNode
@Composable
@ExplicitGroupsComposable
inline fun <T : Any?, E : Applier<*>> ComposeNode(
noinline factory: () -> T,
update: @DisallowComposableCalls Updater<T>.() -> Unit,
noinline skippableUpdate: @Composable SkippableUpdater<T>.() -> Unit,
content: @Composable () -> Unit
): Unit
Emits a node into the composition of type T. Nodes emitted inside of content will become children of the emitted node.
This function will throw a runtime exception if E is not a subtype of the applier of the currentComposer.
import androidx.compose.runtime.AbstractApplier import androidx.compose.runtime.Composable import androidx.compose.runtime.ComposeNode import androidx.compose.runtime.Composition import androidx.compose.runtime.CompositionContext import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember // Provided we have a tree with a node base type like the following abstract class Node { val children = mutableListOf<Node>() } // We would implement an Applier class like the following, which would teach compose how to // manage a tree of Nodes. class NodeApplier(root: Node) : AbstractApplier<Node>(root) { override fun insertTopDown(index: Int, instance: Node) { current.children.add(index, instance) } override fun insertBottomUp(index: Int, instance: Node) { // Ignored as the tree is built top-down. } override fun remove(index: Int, count: Int) { current.children.remove(index, count) } override fun move(from: Int, to: Int, count: Int) { current.children.move(from, to, count) } override fun onClear() { root.children.clear() } } // A function like the following could be created to create a composition provided a root Node. fun Node.setContent(parent: CompositionContext, content: @Composable () -> Unit): Composition { return Composition(NodeApplier(this), parent).apply { setContent(content) } } // assuming we have Node sub-classes like "TextNode" and "GroupNode" class TextNode : Node() { var text: String = "" var onClick: () -> Unit = {} } class GroupNode : Node() // Composable equivalents could be created @Composable fun Text(text: String, onClick: () -> Unit = {}) { ComposeNode<TextNode, NodeApplier>(::TextNode) { set(text) { this.text = it } set(onClick) { this.onClick = it } } } @Composable fun Group(content: @Composable () -> Unit) { ComposeNode<GroupNode, NodeApplier>(::GroupNode, {}, content) } // and then a sample tree could be composed: fun runApp(root: GroupNode, parent: CompositionContext) { root.setContent(parent) { var count by remember { mutableStateOf(0) } Group { Text("Count: $count") Text("Increment") { count++ } } } }
| Parameters | |
|---|---|
noinline factory: () -> T |
A function which will create a new instance of |
update: @DisallowComposableCalls Updater<T>.() -> Unit |
A function to perform updates on the node. This will run every time emit is executed. This function is called in place and will be inlined. |
noinline skippableUpdate: @Composable SkippableUpdater<T>.() -> Unit |
A function to perform updates on the node. Unlike |
content: @Composable () -> Unit |
the composable content that will emit the "children" of this node. |
| See also | |
|---|---|
Updater |
|
SkippableUpdater |
|
Applier |
|
Composition |
Composition
fun Composition(applier: Applier<*>, parent: CompositionContext): Composition
This method is the way to initiate a composition. parent can be
-
provided to make the composition behave as a sub-composition of the parent. If composition does
-
not have a parent,
Recomposerinstance should be provided.
It is important to call Composition.dispose when composition is no longer needed in order to release resources.
import androidx.compose.runtime.AbstractApplier import androidx.compose.runtime.Composable import androidx.compose.runtime.ComposeNode import androidx.compose.runtime.Composition import androidx.compose.runtime.CompositionContext import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember // Provided we have a tree with a node base type like the following abstract class Node { val children = mutableListOf<Node>() } // We would implement an Applier class like the following, which would teach compose how to // manage a tree of Nodes. class NodeApplier(root: Node) : AbstractApplier<Node>(root) { override fun insertTopDown(index: Int, instance: Node) { current.children.add(index, instance) } override fun insertBottomUp(index: Int, instance: Node) { // Ignored as the tree is built top-down. } override fun remove(index: Int, count: Int) { current.children.remove(index, count) } override fun move(from: Int, to: Int, count: Int) { current.children.move(from, to, count) } override fun onClear() { root.children.clear() } } // A function like the following could be created to create a composition provided a root Node. fun Node.setContent(parent: CompositionContext, content: @Composable () -> Unit): Composition { return Composition(NodeApplier(this), parent).apply { setContent(content) } } // assuming we have Node sub-classes like "TextNode" and "GroupNode" class TextNode : Node() { var text: String = "" var onClick: () -> Unit = {} } class GroupNode : Node() // Composable equivalents could be created @Composable fun Text(text: String, onClick: () -> Unit = {}) { ComposeNode<TextNode, NodeApplier>(::TextNode) { set(text) { this.text = it } set(onClick) { this.onClick = it } } } @Composable fun Group(content: @Composable () -> Unit) { ComposeNode<GroupNode, NodeApplier>(::GroupNode, {}, content) } // and then a sample tree could be composed: fun runApp(root: GroupNode, parent: CompositionContext) { root.setContent(parent) { var count by remember { mutableStateOf(0) } Group { Text("Count: $count") Text("Increment") { count++ } } } }
| Parameters | |
|---|---|
applier: Applier<*> |
The |
parent: CompositionContext |
The parent |
| See also | |
|---|---|
Applier |
|
Composition |
|
Recomposer |
Composition
@ExperimentalComposeApi
fun Composition(
applier: Applier<*>,
parent: CompositionContext,
recomposeCoroutineContext: CoroutineContext
): Composition
Create a Composition using applier to manage the composition, as a child of parent.
When used in a configuration that supports concurrent recomposition, hint to the environment that recomposeCoroutineContext should be used to perform recomposition. Recompositions will be launched into the
CompositionLocalProvider
@Composable
fun CompositionLocalProvider(
context: CompositionLocalContext,
content: @Composable () -> Unit
): Unit
CompositionLocalProvider binds values to CompositionLocal's, provided by context. Reading the CompositionLocal using CompositionLocal.current will return the value provided in values stored inside context for all composable functions called directly or indirectly in the content lambda.
import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @Composable fun App(user: User) { CompositionLocalProvider(ActiveUser provides user) { SomeScreen() } }
CompositionLocalProvider
@Composable
@NonSkippableComposable
fun CompositionLocalProvider(
value: ProvidedValue<*>,
content: @Composable () -> Unit
): Unit
CompositionLocalProvider binds value to ProvidableCompositionLocal key. Reading the CompositionLocal using CompositionLocal.current will return the value provided in CompositionLocalProvider's value parameter for all composable functions called directly or indirectly in the content lambda.
import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @Composable fun App(user: User) { CompositionLocalProvider(ActiveUser provides user) { SomeScreen() } }
CompositionLocalProvider
@Composable
@NonSkippableComposable
fun CompositionLocalProvider(
vararg values: ProvidedValue<*>,
content: @Composable () -> Unit
): Unit
CompositionLocalProvider binds values to ProvidableCompositionLocal keys. Reading the CompositionLocal using CompositionLocal.current will return the value provided in CompositionLocalProvider's values parameter for all composable functions called directly or indirectly in the content lambda.
import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @Composable fun App(user: User) { CompositionLocalProvider(ActiveUser provides user) { SomeScreen() } }
ControlledComposition
@TestOnly
fun ControlledComposition(applier: Applier<*>, parent: CompositionContext): ControlledComposition
This method is a way to initiate a composition. Optionally, a parent can be provided to make the composition behave as a sub-composition of the parent or a Recomposer can be provided.
A controlled composition allows direct control of the composition instead of it being controlled by the Recomposer passed ot the root composition.
It is important to call Composition.dispose this composer is no longer needed in order to release resources.
import androidx.compose.runtime.AbstractApplier import androidx.compose.runtime.Composable import androidx.compose.runtime.ComposeNode import androidx.compose.runtime.Composition import androidx.compose.runtime.CompositionContext import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember // Provided we have a tree with a node base type like the following abstract class Node { val children = mutableListOf<Node>() } // We would implement an Applier class like the following, which would teach compose how to // manage a tree of Nodes. class NodeApplier(root: Node) : AbstractApplier<Node>(root) { override fun insertTopDown(index: Int, instance: Node) { current.children.add(index, instance) } override fun insertBottomUp(index: Int, instance: Node) { // Ignored as the tree is built top-down. } override fun remove(index: Int, count: Int) { current.children.remove(index, count) } override fun move(from: Int, to: Int, count: Int) { current.children.move(from, to, count) } override fun onClear() { root.children.clear() } } // A function like the following could be created to create a composition provided a root Node. fun Node.setContent(parent: CompositionContext, content: @Composable () -> Unit): Composition { return Composition(NodeApplier(this), parent).apply { setContent(content) } } // assuming we have Node sub-classes like "TextNode" and "GroupNode" class TextNode : Node() { var text: String = "" var onClick: () -> Unit = {} } class GroupNode : Node() // Composable equivalents could be created @Composable fun Text(text: String, onClick: () -> Unit = {}) { ComposeNode<TextNode, NodeApplier>(::TextNode) { set(text) { this.text = it } set(onClick) { this.onClick = it } } } @Composable fun Group(content: @Composable () -> Unit) { ComposeNode<GroupNode, NodeApplier>(::GroupNode, {}, content) } // and then a sample tree could be composed: fun runApp(root: GroupNode, parent: CompositionContext) { root.setContent(parent) { var count by remember { mutableStateOf(0) } Group { Text("Count: $count") Text("Increment") { count++ } } } }
| Parameters | |
|---|---|
applier: Applier<*> |
The |
parent: CompositionContext |
The parent |
| See also | |
|---|---|
Applier |
|
Composition |
|
Recomposer |
ControlledComposition
@TestOnly
@ExperimentalComposeApi
fun ControlledComposition(
applier: Applier<*>,
parent: CompositionContext,
recomposeCoroutineContext: CoroutineContext
): ControlledComposition
DisposableEffect
@Composable
@NonRestartableComposable
funDisposableEffect(effect: DisposableEffectScope.() -> DisposableEffectResult): Unit
A side effect of composition that must be reversed or cleaned up if the DisposableEffect leaves the composition.
It is an error to call DisposableEffect without at least one key parameter.
DisposableEffect
@Composable
@NonRestartableComposable
fun DisposableEffect(key1: Any?, effect: DisposableEffectScope.() -> DisposableEffectResult): Unit
A side effect of composition that must run for any new unique value of key1 and must be reversed or cleaned up if key1 changes or if the DisposableEffect leaves the composition.
A DisposableEffect's key is a value that defines the identity of the DisposableEffect. If a key changes, the DisposableEffect must dispose its current effect and reset by calling effect again. Examples of keys include:
-
Observable objects that the effect subscribes to
-
Unique request parameters to an operation that must cancel and retry if those parameters change
DisposableEffect may be used to initialize or subscribe to a key and reinitialize when a different key is provided, performing cleanup for the old operation before initializing the new. For example:
import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @Composable fun UserProfile(userRepository: UserRepository, userRequest: UserDataRequest) { var userDataState by remember { mutableStateOf<UserDataState>(UserDataState.Loading) } // If either the repository or request change, we must cancel our old data fetch // and begin a new data fetch. We will cancel the current data fetch if UserProfile // leaves the composition. DisposableEffect(userRepository, userRequest) { val requestDisposable = userRepository.fetchUserData( userRequest, onSuccess = { response -> userDataState = UserDataState.UserData(response) }, onError = { throwable -> userDataState = UserDataState.Error(throwable.message) }, ) onDispose { requestDisposable.dispose() } } // ... }
A DisposableEffect must include an onDispose clause as the final statement in its effect block. If your operation does not require disposal it might be a SideEffect instead, or a LaunchedEffect if it launches a coroutine that should be managed by the composition.
There is guaranteed to be one call to dispose for every call to effect. Both effect and dispose will always be run on the composition's apply dispatcher and appliers are never run concurrent with themselves, one another, applying changes to the composition tree, or running RememberObserver event callbacks.
DisposableEffect
@Composable
@NonRestartableComposable
fun DisposableEffect(vararg keys: Any?, effect: DisposableEffectScope.() -> DisposableEffectResult): Unit
A side effect of composition that must run for any new unique value of keys and must be reversed or cleaned up if any keys change or if the DisposableEffect leaves the composition.
A DisposableEffect's key is a value that defines the identity of the DisposableEffect. If a key changes, the DisposableEffect must dispose its current effect and reset by calling effect again. Examples of keys include:
-
Observable objects that the effect subscribes to
-
Unique request parameters to an operation that must cancel and retry if those parameters change
DisposableEffect may be used to initialize or subscribe to a key and reinitialize when a different key is provided, performing cleanup for the old operation before initializing the new. For example:
import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @Composable fun UserProfile(userRepository: UserRepository, userRequest: UserDataRequest) { var userDataState by remember { mutableStateOf<UserDataState>(UserDataState.Loading) } // If either the repository or request change, we must cancel our old data fetch // and begin a new data fetch. We will cancel the current data fetch if UserProfile // leaves the composition. DisposableEffect(userRepository, userRequest) { val requestDisposable = userRepository.fetchUserData( userRequest, onSuccess = { response -> userDataState = UserDataState.UserData(response) }, onError = { throwable -> userDataState = UserDataState.Error(throwable.message) }, ) onDispose { requestDisposable.dispose() } } // ... }
A DisposableEffect must include an onDispose clause as the final statement in its effect block. If your operation does not require disposal it might be a SideEffect instead, or a LaunchedEffect if it launches a coroutine that should be managed by the composition.
There is guaranteed to be one call to dispose for every call to effect. Both effect and dispose will always be run on the composition's apply dispatcher and appliers are never run concurrent with themselves, one another, applying changes to the composition tree, or running RememberObserver event callbacks.
DisposableEffect
@Composable
@NonRestartableComposable
fun DisposableEffect(key1: Any?, key2: Any?, effect: DisposableEffectScope.() -> DisposableEffectResult): Unit
A side effect of composition that must run for any new unique value of key1 or key2 and must be reversed or cleaned up if key1 or key2 changes, or if the DisposableEffect leaves the composition.
A DisposableEffect's key is a value that defines the identity of the DisposableEffect. If a key changes, the DisposableEffect must dispose its current effect and reset by calling effect again. Examples of keys include:
-
Observable objects that the effect subscribes to
-
Unique request parameters to an operation that must cancel and retry if those parameters change
DisposableEffect may be used to initialize or subscribe to a key and reinitialize when a different key is provided, performing cleanup for the old operation before initializing the new. For example:
import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @Composable fun UserProfile(userRepository: UserRepository, userRequest: UserDataRequest) { var userDataState by remember { mutableStateOf<UserDataState>(UserDataState.Loading) } // If either the repository or request change, we must cancel our old data fetch // and begin a new data fetch. We will cancel the current data fetch if UserProfile // leaves the composition. DisposableEffect(userRepository, userRequest) { val requestDisposable = userRepository.fetchUserData( userRequest, onSuccess = { response -> userDataState = UserDataState.UserData(response) }, onError = { throwable -> userDataState = UserDataState.Error(throwable.message) }, ) onDispose { requestDisposable.dispose() } } // ... }
A DisposableEffect must include an onDispose clause as the final statement in its effect block. If your operation does not require disposal it might be a SideEffect instead, or a LaunchedEffect if it launches a coroutine that should be managed by the composition.
There is guaranteed to be one call to dispose for every call to effect. Both effect and dispose will always be run on the composition's apply dispatcher and appliers are never run concurrent with themselves, one another, applying changes to the composition tree, or running RememberObserver event callbacks.
DisposableEffect
@Composable
@NonRestartableComposable
fun DisposableEffect(
key1: Any?,
key2: Any?,
key3: Any?,
effect: DisposableEffectScope.() -> DisposableEffectResult
): Unit
A side effect of composition that must run for any new unique value of key1, key2 or key3 and must be reversed or cleaned up if key1, key2 or key3 changes, or if the DisposableEffect leaves the composition.
A DisposableEffect's key is a value that defines the identity of the DisposableEffect. If a key changes, the DisposableEffect must dispose its current effect and reset by calling effect again. Examples of keys include:
-
Observable objects that the effect subscribes to
-
Unique request parameters to an operation that must cancel and retry if those parameters change
DisposableEffect may be used to initialize or subscribe to a key and reinitialize when a different key is provided, performing cleanup for the old operation before initializing the new. For example:
import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @Composable fun UserProfile(userRepository: UserRepository, userRequest: UserDataRequest) { var userDataState by remember { mutableStateOf<UserDataState>(UserDataState.Loading) } // If either the repository or request change, we must cancel our old data fetch // and begin a new data fetch. We will cancel the current data fetch if UserProfile // leaves the composition. DisposableEffect(userRepository, userRequest) { val requestDisposable = userRepository.fetchUserData( userRequest, onSuccess = { response -> userDataState = UserDataState.UserData(response) }, onError = { throwable -> userDataState = UserDataState.Error(throwable.message) }, ) onDispose { requestDisposable.dispose() } } // ... }
A DisposableEffect must include an onDispose clause as the final statement in its effect block. If your operation does not require disposal it might be a SideEffect instead, or a LaunchedEffect if it launches a coroutine that should be managed by the composition.
There is guaranteed to be one call to dispose for every call to effect. Both effect and dispose will always be run on the composition's apply dispatcher and appliers are never run concurrent with themselves, one another, applying changes to the composition tree, or running RememberObserver event callbacks.
LaunchedEffect
@Composable
funLaunchedEffect(block: suspend CoroutineScope.() -> Unit): Unit
When LaunchedEffect enters the composition it will launch block into the composition's CoroutineContext. The coroutine will be cancelled when the LaunchedEffect leaves the composition.
It is an error to call LaunchedEffect without at least one key parameter.
LaunchedEffect
@Composable
@NonRestartableComposable
fun LaunchedEffect(key1: Any?, block: suspend CoroutineScope.() -> Unit): Unit
When LaunchedEffect enters the composition it will launch block into the composition's CoroutineContext. The coroutine will be cancelled and re-launched when LaunchedEffect is recomposed with a different key1. The coroutine will be cancelled when the LaunchedEffect leaves the composition.
This function should not be used to (re-)launch ongoing tasks in response to callback events by way of storing callback data in MutableState passed to key1. Instead, see rememberCoroutineScope to obtain a CoroutineScope that may be used to launch ongoing jobs scoped to the composition in response to event callbacks.
LaunchedEffect
@Composable
@NonRestartableComposable
fun LaunchedEffect(vararg keys: Any?, block: suspend CoroutineScope.() -> Unit): Unit
When LaunchedEffect enters the composition it will launch block into the composition's CoroutineContext. The coroutine will be cancelled and re-launched when LaunchedEffect is recomposed with any different keys. The coroutine will be cancelled when the LaunchedEffect leaves the composition.
This function should not be used to (re-)launch ongoing tasks in response to callback events by way of storing callback data in MutableState passed to key. Instead, see rememberCoroutineScope to obtain a CoroutineScope that may be used to launch ongoing jobs scoped to the composition in response to event callbacks.
LaunchedEffect
@Composable
@NonRestartableComposable
fun LaunchedEffect(key1: Any?, key2: Any?, block: suspend CoroutineScope.() -> Unit): Unit
When LaunchedEffect enters the composition it will launch block into the composition's CoroutineContext. The coroutine will be cancelled and re-launched when LaunchedEffect is recomposed with a different key1 or key2. The coroutine will be cancelled when the LaunchedEffect leaves the composition.
This function should not be used to (re-)launch ongoing tasks in response to callback events by way of storing callback data in MutableState passed to key. Instead, see rememberCoroutineScope to obtain a CoroutineScope that may be used to launch ongoing jobs scoped to the composition in response to event callbacks.
LaunchedEffect
@Composable
@NonRestartableComposable
fun LaunchedEffect(key1: Any?, key2: Any?, key3: Any?, block: suspend CoroutineScope.() -> Unit): Unit
When LaunchedEffect enters the composition it will launch block into the composition's CoroutineContext. The coroutine will be cancelled and re-launched when LaunchedEffect is recomposed with a different key1, key2 or key3. The coroutine will be cancelled when the LaunchedEffect leaves the composition.
This function should not be used to (re-)launch ongoing tasks in response to callback events by way of storing callback data in MutableState passed to key. Instead, see rememberCoroutineScope to obtain a CoroutineScope that may be used to launch ongoing jobs scoped to the composition in response to event callbacks.
PausableComposition
fun PausableComposition(applier: Applier<*>, parent: CompositionContext): PausableComposition
Create a PausableComposition. A PausableComposition can create a PausedComposition which allows pausing and resuming the composition.
| Parameters | |
|---|---|
applier: Applier<*> |
The |
parent: CompositionContext |
The parent |
| See also | |
|---|---|
Applier |
|
CompositionContext |
|
PausableComposition |
ReusableComposeNode
@Composable
inline fun <T : Any, E : Applier<*>> ReusableComposeNode(
noinline factory: () -> T,
update: @DisallowComposableCalls Updater<T>.() -> Unit
): Unit
Emits a recyclable node into the composition of type T.
This function will throw a runtime exception if E is not a subtype of the applier of the currentComposer.
import androidx.compose.runtime.AbstractApplier import androidx.compose.runtime.Composable import androidx.compose.runtime.ComposeNode import androidx.compose.runtime.Composition import androidx.compose.runtime.CompositionContext import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember // Provided we have a tree with a node base type like the following abstract class Node { val children = mutableListOf<Node>() } // We would implement an Applier class like the following, which would teach compose how to // manage a tree of Nodes. class NodeApplier(root: Node) : AbstractApplier<Node>(root) { override fun insertTopDown(index: Int, instance: Node) { current.children.add(index, instance) } override fun insertBottomUp(index: Int, instance: Node) { // Ignored as the tree is built top-down. } override fun remove(index: Int, count: Int) { current.children.remove(index, count) } override fun move(from: Int, to: Int, count: Int) { current.children.move(from, to, count) } override fun onClear() { root.children.clear() } } // A function like the following could be created to create a composition provided a root Node. fun Node.setContent(parent: CompositionContext, content: @Composable () -> Unit): Composition { return Composition(NodeApplier(this), parent).apply { setContent(content) } } // assuming we have Node sub-classes like "TextNode" and "GroupNode" class TextNode : Node() { var text: String = "" var onClick: () -> Unit = {} } class GroupNode : Node() // Composable equivalents could be created @Composable fun Text(text: String, onClick: () -> Unit = {}) { ComposeNode<TextNode, NodeApplier>(::TextNode) { set(text) { this.text = it } set(onClick) { this.onClick = it } } } @Composable fun Group(content: @Composable () -> Unit) { ComposeNode<GroupNode, NodeApplier>(::GroupNode, {}, content) } // and then a sample tree could be composed: fun runApp(root: GroupNode, parent: CompositionContext) { root.setContent(parent) { var count by remember { mutableStateOf(0) } Group { Text("Count: $count") Text("Increment") { count++ } } } }
| Parameters | |
|---|---|
noinline factory: () -> T |
A function which will create a new instance of |
update: @DisallowComposableCalls Updater<T>.() -> Unit |
A function to perform updates on the node. This will run every time emit is executed. This function is called in place and will be inlined. |
| See also | |
|---|---|
Updater |
|
Applier |
|
Composition |
ReusableComposeNode
@Composable
inline fun <T : Any?, E : Applier<*>> ReusableComposeNode(
noinline factory: () -> T,
update: @DisallowComposableCalls Updater<T>.() -> Unit,
content: @Composable () -> Unit
): Unit
Emits a recyclable node into the composition of type T. Nodes emitted inside of content will become children of the emitted node.
This function will throw a runtime exception if E is not a subtype of the applier of the currentComposer.
import androidx.compose.runtime.AbstractApplier import androidx.compose.runtime.Composable import androidx.compose.runtime.ComposeNode import androidx.compose.runtime.Composition import androidx.compose.runtime.CompositionContext import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember // Provided we have a tree with a node base type like the following abstract class Node { val children = mutableListOf<Node>() } // We would implement an Applier class like the following, which would teach compose how to // manage a tree of Nodes. class NodeApplier(root: Node) : AbstractApplier<Node>(root) { override fun insertTopDown(index: Int, instance: Node) { current.children.add(index, instance) } override fun insertBottomUp(index: Int, instance: Node) { // Ignored as the tree is built top-down. } override fun remove(index: Int, count: Int) { current.children.remove(index, count) } override fun move(from: Int, to: Int, count: Int) { current.children.move(from, to, count) } override fun onClear() { root.children.clear() } } // A function like the following could be created to create a composition provided a root Node. fun Node.setContent(parent: CompositionContext, content: @Composable () -> Unit): Composition { return Composition(NodeApplier(this), parent).apply { setContent(content) } } // assuming we have Node sub-classes like "TextNode" and "GroupNode" class TextNode : Node() { var text: String = "" var onClick: () -> Unit = {} } class GroupNode : Node() // Composable equivalents could be created @Composable fun Text(text: String, onClick: () -> Unit = {}) { ComposeNode<TextNode, NodeApplier>(::TextNode) { set(text) { this.text = it } set(onClick) { this.onClick = it } } } @Composable fun Group(content: @Composable () -> Unit) { ComposeNode<GroupNode, NodeApplier>(::GroupNode, {}, content) } // and then a sample tree could be composed: fun runApp(root: GroupNode, parent: CompositionContext) { root.setContent(parent) { var count by remember { mutableStateOf(0) } Group { Text("Count: $count") Text("Increment") { count++ } } } }
| Parameters | |
|---|---|
noinline factory: () -> T |
A function which will create a new instance of |
update: @DisallowComposableCalls Updater<T>.() -> Unit |
A function to perform updates on the node. This will run every time emit is executed. This function is called in place and will be inlined. |
content: @Composable () -> Unit |
the composable content that will emit the "children" of this node. |
| See also | |
|---|---|
Updater |
|
Applier |
|
Composition |
ReusableComposeNode
@Composable
@ExplicitGroupsComposable
inline fun <T : Any?, E : Applier<*>> ReusableComposeNode(
noinline factory: () -> T,
update: @DisallowComposableCalls Updater<T>.() -> Unit,
noinline skippableUpdate: @Composable SkippableUpdater<T>.() -> Unit,
content: @Composable () -> Unit
): Unit
Emits a recyclable node into the composition of type T. Nodes emitted inside of content will become children of the emitted node.
This function will throw a runtime exception if E is not a subtype of the applier of the currentComposer.
import androidx.compose.runtime.AbstractApplier import androidx.compose.runtime.Composable import androidx.compose.runtime.ComposeNode import androidx.compose.runtime.Composition import androidx.compose.runtime.CompositionContext import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember // Provided we have a tree with a node base type like the following abstract class Node { val children = mutableListOf<Node>() } // We would implement an Applier class like the following, which would teach compose how to // manage a tree of Nodes. class NodeApplier(root: Node) : AbstractApplier<Node>(root) { override fun insertTopDown(index: Int, instance: Node) { current.children.add(index, instance) } override fun insertBottomUp(index: Int, instance: Node) { // Ignored as the tree is built top-down. } override fun remove(index: Int, count: Int) { current.children.remove(index, count) } override fun move(from: Int, to: Int, count: Int) { current.children.move(from, to, count) } override fun onClear() { root.children.clear() } } // A function like the following could be created to create a composition provided a root Node. fun Node.setContent(parent: CompositionContext, content: @Composable () -> Unit): Composition { return Composition(NodeApplier(this), parent).apply { setContent(content) } } // assuming we have Node sub-classes like "TextNode" and "GroupNode" class TextNode : Node() { var text: String = "" var onClick: () -> Unit = {} } class GroupNode : Node() // Composable equivalents could be created @Composable fun Text(text: String, onClick: () -> Unit = {}) { ComposeNode<TextNode, NodeApplier>(::TextNode) { set(text) { this.text = it } set(onClick) { this.onClick = it } } } @Composable fun Group(content: @Composable () -> Unit) { ComposeNode<GroupNode, NodeApplier>(::GroupNode, {}, content) } // and then a sample tree could be composed: fun runApp(root: GroupNode, parent: CompositionContext) { root.setContent(parent) { var count by remember { mutableStateOf(0) } Group { Text("Count: $count") Text("Increment") { count++ } } } }
| Parameters | |
|---|---|
noinline factory: () -> T |
A function which will create a new instance of |
update: @DisallowComposableCalls Updater<T>.() -> Unit |
A function to perform updates on the node. This will run every time emit is executed. This function is called in place and will be inlined. |
noinline skippableUpdate: @Composable SkippableUpdater<T>.() -> Unit |
A function to perform updates on the node. Unlike |
content: @Composable () -> Unit |
the composable content that will emit the "children" of this node. |
| See also | |
|---|---|
Updater |
|
SkippableUpdater |
|
Applier |
|
Composition |
ReusableComposition
fun ReusableComposition(applier: Applier<*>, parent: CompositionContext): ReusableComposition
This method is the way to initiate a reusable composition. parent can be provided to make the composition behave as a sub-composition of the parent. If composition does not have a parent, Recomposer instance should be provided.
It is important to call Composition.dispose when composition is no longer needed in order to release resources.
| Parameters | |
|---|---|
applier: Applier<*> |
The |
parent: CompositionContext |
The parent |
ReusableContent
@Composable
inline fun ReusableContent(key: Any?, content: @Composable () -> Unit): Unit
A utility function to mark a composition as supporting recycling. If the key changes the composition is replaced by a new composition (as would happen for key) but reusable nodes that are emitted by ReusableComposeNode are reused.
| Parameters | |
|---|---|
key: Any? |
the value that is used to trigger recycling. If recomposed with a different value the composer creates a new composition but tries to reuse reusable nodes. |
content: @Composable () -> Unit |
the composable children that are recyclable. |
ReusableContentHost
@Composable
@ExplicitGroupsComposable
inline fun ReusableContentHost(
active: Boolean,
crossinline content: @Composable () -> Unit
): Unit
An optional utility function used when hosting ReusableContent. If active is false the content is treated as if it is deleted by removing all remembered objects from the composition but the node produced for the tree are not removed. When the composition later becomes active then the nodes are able to be reused inside ReusableContent content without requiring the remembered state of the composition's lifetime being arbitrarily extended.
| Parameters | |
|---|---|
active: Boolean |
when |
crossinline content: @Composable () -> Unit |
the composable content that is managed by this composable. |
SideEffect
@Composable
@NonRestartableComposable
@ExplicitGroupsComposable
fun SideEffect(effect: () -> Unit): Unit
Schedule effect to run when the current composition completes successfully and applies changes. SideEffect can be used to apply side effects to objects managed by the composition that are not backed by snapshots so as not to leave those objects in an inconsistent state if the current composition operation fails.
effect will always be run on the composition's apply dispatcher and appliers are never run concurrent with themselves, one another, applying changes to the composition tree, or running RememberObserver event callbacks. SideEffects are always run after RememberObserver event callbacks.
A SideEffect runs after every recomposition. To launch an ongoing task spanning potentially many recompositions, see LaunchedEffect. To manage an event subscription or other object lifecycle, see DisposableEffect.
clearCompositionErrors
@TestOnly
fun clearCompositionErrors(): Unit
Clears current composition errors in hot reload mode. Test-only API, not for use in production.
compositionLocalOf
fun <T : Any?> compositionLocalOf(
policy: SnapshotMutationPolicy<T> = structuralEqualityPolicy(),
defaultFactory: () -> T
): ProvidableCompositionLocal<T>
Create a CompositionLocal key that can be provided using CompositionLocalProvider. Changing the value provided during recomposition will invalidate the content of CompositionLocalProvider that read the value using CompositionLocal.current.
compositionLocalOf creates a ProvidableCompositionLocal which can be used in a a call to CompositionLocalProvider. Similar to MutableList vs. List, if the key is made public as CompositionLocal instead of ProvidableCompositionLocal, it can be read using CompositionLocal.current but not re-provided.
| Parameters | |
|---|---|
policy: SnapshotMutationPolicy<T> = structuralEqualityPolicy() |
a policy to determine when a |
defaultFactory: () -> T |
a value factory to supply a value when a value is not provided. This factory is called when no value is provided through a |
compositionLocalWithComputedDefaultOf
fun <T : Any?> 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.
import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.compositionLocalWithComputedDefaultOf val LocalBaseValue = compositionLocalOf { 10 } val LocalLargerValue = compositionLocalWithComputedDefaultOf { LocalBaseValue.currentValue + 10 }
import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.compositionLocalWithComputedDefaultOf 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 } } } }
| Parameters | |
|---|---|
defaultComputation: CompositionLocalAccessorScope.() -> T |
the default computation to use when this |
currentCompositionErrors
@TestOnly
funcurrentCompositionErrors(): List<Pair<Exception, Boolean>>
Get list of errors captured in composition. This list is only available when recomposer is in hot reload mode. Test-only API, not for use in production.
derivedStateOf
@StateFactoryMarker
fun <T : Any?> derivedStateOf(calculation: () -> T): State<T>
Creates a State object whose State.value is the result of calculation. The result of calculation will be cached in such a way that calling State.value repeatedly will not cause calculation to be executed multiple times, but reading State.value will cause all State objects that got read during the calculation to be read in the current Snapshot, meaning that this will correctly subscribe to the derived state objects if the value is being read in an observed context such as a Composable function. Derived states without mutation policy trigger updates on each dependency change. To avoid invalidation on update, provide suitable SnapshotMutationPolicy through derivedStateOf overload.
import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @Composable fun CountDisplay(count: State<Int>) { Text("Count: ${count.value}") } @Composable fun Example() { var a by remember { mutableStateOf(0) } var b by remember { mutableStateOf(0) } val sum = remember { derivedStateOf { a + b } } // Changing either a or b will cause CountDisplay to recompose but not trigger Example // to recompose. CountDisplay(sum) }
| Parameters | |
|---|---|
calculation: () -> T |
the calculation to create the value this state object represents. |
derivedStateOf
@StateFactoryMarker
fun <T : Any?> derivedStateOf(
policy: SnapshotMutationPolicy<T>,
calculation: () -> T
): State<T>
Creates a State object whose State.value is the result of calculation. The result of calculation will be cached in such a way that calling State.value repeatedly will not cause calculation to be executed multiple times, but reading State.value will cause all State objects that got read during the calculation to be read in the current Snapshot, meaning that this will correctly subscribe to the derived state objects if the value is being read in an observed context such as a Composable function.
import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @Composable fun CountDisplay(count: State<Int>) { Text("Count: ${count.value}") } @Composable fun Example() { var a by remember { mutableStateOf(0) } var b by remember { mutableStateOf(0) } val sum = remember { derivedStateOf { a + b } } // Changing either a or b will cause CountDisplay to recompose but not trigger Example // to recompose. CountDisplay(sum) }
| Parameters | |
|---|---|
policy: SnapshotMutationPolicy<T> |
mutation policy to control when changes to the |
calculation: () -> T |
the calculation to create the value this state object represents. |
disableHotReloadMode
@TestOnly
fun disableHotReloadMode(): Unit
Disables hot reload mode in recomposer. Test-only API, not for use in production.
invalidateGroupsWithKey
@TestOnly
fun invalidateGroupsWithKey(key: Int): Unit
Invalidates composed groups with the given key. Calling this method switches recomposer into hot reload mode. Test-only API, not for use in production.
| Parameters | |
|---|---|
key: Int |
group key to invalidate. |
isTraceInProgress
@ComposeCompilerApi
fun isTraceInProgress(): Boolean
Internal tracing API.
Should be called without thread synchronization with occasional information loss.
key
@Composable
inline fun <T : Any?> key(vararg keys: Any?, block: @Composable () -> T): T
key is a utility composable that is used to "group" or "key" a block of execution inside of a composition. This is sometimes needed for correctness inside of control-flow that may cause a given composable invocation to execute more than once during composition.
The value for a key does not need to be globally unique, and needs only be unique amongst the invocations of key at that point in composition.
For instance, consider the following example:
import androidx.compose.runtime.key for (user in users) { key(user.id) { UserPreview(user = user) } } for (user in users.filter { isAdmin }) { key(user.id) { Friend(friend = user) } }
Even though there are users with the same id composed in both the top and the bottom loop, because they are different calls to key, there is no need to create compound keys.
The key must be unique for each element in the collection, however, or children and local state might be reused in unintended ways.
For instance, consider the following example:
import androidx.compose.runtime.key for ((child, parent) in relationships) { key(parent.id) { User(user = child) User(user = parent) } }
This example assumes that parent.id is a unique key for each item in the collection, but this is only true if it is fair to assume that a parent will only ever have a single child, which may not be the case. Instead, it may be more correct to do the following:
import androidx.compose.runtime.key for ((child, parent) in relationships) { key(parent.id to child.id) { User(user = child) User(user = parent) } }
A compound key can be created by passing in multiple arguments:
import androidx.compose.runtime.State import androidx.compose.runtime.key import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember for (element in elements) { val selected by key(element.id, parentId) { remember { mutableStateOf(false) } } ListItem(item = element, selected = selected) }
| Parameters | |
|---|---|
vararg keys: Any? |
The set of values to be used to create a compound key. These will be compared to their previous values using |
block: @Composable () -> T |
The composable children for this group. |
movableContentOf
@RememberInComposition
fun movableContentOf(content: @Composable () -> Unit): @Composable () -> Unit
Convert a lambda into one that moves the remembered state and nodes created in a previous call to the new location it is called.
Tracking compositions can be used to produce a composable that moves its content between a row and a column based on a parameter, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val movableContent = remember(content) { movableContentOf(content) } if (vertical) { Column { movableContent() } } else { Row { movableContent() } }
Or they can be used to ensure the composition state tracks with a model as moves in the layout, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.Composable import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val itemMap = remember { mutableMapOf<Item, @Composable () -> Unit>() } val movableItems = items.map { item -> itemMap.getOrPut(item) { movableContentOf { ItemView(item) } } } val itemsPerColumn = 10 val columns = items.size / itemsPerColumn + (if (items.size % itemsPerColumn == 0) 0 else 1) Row { repeat(columns) { column -> Column { val base = column * itemsPerColumn val end = minOf(base + itemsPerColumn, items.size) for (index in base until end) { movableItems[index]() } } } }
| Parameters | |
|---|---|
content: @Composable () -> Unit |
The composable lambda to convert into a state tracking lambda. |
| Returns | |
|---|---|
@Composable () -> Unit |
A tracking composable lambda |
movableContentOf
@RememberInComposition
fun <P : Any?> movableContentOf(content: @Composable (P) -> Unit): @Composable (P) -> Unit
Convert a lambda into one that moves the remembered state and nodes created in a previous call to the new location it is called.
Tracking compositions can be used to produce a composable that moves its content between a row and a column based on a parameter, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val movableContent = remember(content) { movableContentOf(content) } if (vertical) { Column { movableContent() } } else { Row { movableContent() } }
Or they can be used to ensure the composition state tracks with a model as moves in the layout, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.Composable import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val itemMap = remember { mutableMapOf<Item, @Composable () -> Unit>() } val movableItems = items.map { item -> itemMap.getOrPut(item) { movableContentOf { ItemView(item) } } } val itemsPerColumn = 10 val columns = items.size / itemsPerColumn + (if (items.size % itemsPerColumn == 0) 0 else 1) Row { repeat(columns) { column -> Column { val base = column * itemsPerColumn val end = minOf(base + itemsPerColumn, items.size) for (index in base until end) { movableItems[index]() } } } }
| Parameters | |
|---|---|
content: @Composable (P) -> Unit |
The composable lambda to convert into a state tracking lambda. |
| Returns | |
|---|---|
@Composable (P) -> Unit |
A tracking composable lambda |
movableContentOf
@RememberInComposition
fun <P1 : Any?, P2 : Any?> movableContentOf(content: @Composable (P1, P2) -> Unit): @Composable (P1, P2) -> Unit
Convert a lambda into one that moves the remembered state and nodes created in a previous call to the new location it is called.
Tracking compositions can be used to produce a composable that moves its content between a row and a column based on a parameter, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val movableContent = remember(content) { movableContentOf(content) } if (vertical) { Column { movableContent() } } else { Row { movableContent() } }
Or they can be used to ensure the composition state tracks with a model as moves in the layout, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.Composable import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val itemMap = remember { mutableMapOf<Item, @Composable () -> Unit>() } val movableItems = items.map { item -> itemMap.getOrPut(item) { movableContentOf { ItemView(item) } } } val itemsPerColumn = 10 val columns = items.size / itemsPerColumn + (if (items.size % itemsPerColumn == 0) 0 else 1) Row { repeat(columns) { column -> Column { val base = column * itemsPerColumn val end = minOf(base + itemsPerColumn, items.size) for (index in base until end) { movableItems[index]() } } } }
| Parameters | |
|---|---|
content: @Composable (P1, P2) -> Unit |
The composable lambda to convert into a state tracking lambda. |
| Returns | |
|---|---|
@Composable (P1, P2) -> Unit |
A tracking composable lambda |
movableContentOf
@RememberInComposition
fun <P1 : Any?, P2 : Any?, P3 : Any?> movableContentOf(
content: @Composable (P1, P2, P3) -> Unit
): @Composable (P1, P2, P3) -> Unit
Convert a lambda into one that moves the remembered state and nodes created in a previous call to the new location it is called.
Tracking compositions can be used to produce a composable that moves its content between a row and a column based on a parameter, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val movableContent = remember(content) { movableContentOf(content) } if (vertical) { Column { movableContent() } } else { Row { movableContent() } }
Or they can be used to ensure the composition state tracks with a model as moves in the layout, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.Composable import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val itemMap = remember { mutableMapOf<Item, @Composable () -> Unit>() } val movableItems = items.map { item -> itemMap.getOrPut(item) { movableContentOf { ItemView(item) } } } val itemsPerColumn = 10 val columns = items.size / itemsPerColumn + (if (items.size % itemsPerColumn == 0) 0 else 1) Row { repeat(columns) { column -> Column { val base = column * itemsPerColumn val end = minOf(base + itemsPerColumn, items.size) for (index in base until end) { movableItems[index]() } } } }
| Parameters | |
|---|---|
content: @Composable (P1, P2, P3) -> Unit |
The composable lambda to convert into a state tracking lambda. |
| Returns | |
|---|---|
@Composable (P1, P2, P3) -> Unit |
A tracking composable lambda |
movableContentOf
@RememberInComposition
fun <P1 : Any?, P2 : Any?, P3 : Any?, P4 : Any?> movableContentOf(
content: @Composable (P1, P2, P3, P4) -> Unit
): @Composable (P1, P2, P3, P4) -> Unit
Convert a lambda into one that moves the remembered state and nodes created in a previous call to the new location it is called.
Tracking compositions can be used to produce a composable that moves its content between a row and a column based on a parameter, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val movableContent = remember(content) { movableContentOf(content) } if (vertical) { Column { movableContent() } } else { Row { movableContent() } }
Or they can be used to ensure the composition state tracks with a model as moves in the layout, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.Composable import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val itemMap = remember { mutableMapOf<Item, @Composable () -> Unit>() } val movableItems = items.map { item -> itemMap.getOrPut(item) { movableContentOf { ItemView(item) } } } val itemsPerColumn = 10 val columns = items.size / itemsPerColumn + (if (items.size % itemsPerColumn == 0) 0 else 1) Row { repeat(columns) { column -> Column { val base = column * itemsPerColumn val end = minOf(base + itemsPerColumn, items.size) for (index in base until end) { movableItems[index]() } } } }
| Parameters | |
|---|---|
content: @Composable (P1, P2, P3, P4) -> Unit |
The composable lambda to convert into a state tracking lambda. |
| Returns | |
|---|---|
@Composable (P1, P2, P3, P4) -> Unit |
A tracking composable lambda |
movableContentWithReceiverOf
@RememberInComposition
fun <R : Any?> movableContentWithReceiverOf(content: @Composable R.() -> Unit): @Composable R.() -> Unit
Convert a lambda with a receiver into one that moves the remembered state and nodes created in a previous call to the new location it is called.
Tracking compositions can be used to produce a composable that moves its content between a row and a column based on a parameter, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val movableContent = remember(content) { movableContentOf(content) } if (vertical) { Column { movableContent() } } else { Row { movableContent() } }
Or they can be used to ensure the composition state tracks with a model as moves in the layout, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.Composable import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val itemMap = remember { mutableMapOf<Item, @Composable () -> Unit>() } val movableItems = items.map { item -> itemMap.getOrPut(item) { movableContentOf { ItemView(item) } } } val itemsPerColumn = 10 val columns = items.size / itemsPerColumn + (if (items.size % itemsPerColumn == 0) 0 else 1) Row { repeat(columns) { column -> Column { val base = column * itemsPerColumn val end = minOf(base + itemsPerColumn, items.size) for (index in base until end) { movableItems[index]() } } } }
| Parameters | |
|---|---|
content: @Composable R.() -> Unit |
The composable lambda to convert into a state tracking lambda. |
| Returns | |
|---|---|
@Composable R.() -> Unit |
A tracking composable lambda |
movableContentWithReceiverOf
@RememberInComposition
fun <R : Any?, P : Any?> movableContentWithReceiverOf(content: @Composable R.(P) -> Unit): @Composable R.(P) -> Unit
Convert a lambda with a receiver into one that moves the remembered state and nodes created in a previous call to the new location it is called.
Tracking compositions can be used to produce a composable that moves its content between a row and a column based on a parameter, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val movableContent = remember(content) { movableContentOf(content) } if (vertical) { Column { movableContent() } } else { Row { movableContent() } }
Or they can be used to ensure the composition state tracks with a model as moves in the layout, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.Composable import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val itemMap = remember { mutableMapOf<Item, @Composable () -> Unit>() } val movableItems = items.map { item -> itemMap.getOrPut(item) { movableContentOf { ItemView(item) } } } val itemsPerColumn = 10 val columns = items.size / itemsPerColumn + (if (items.size % itemsPerColumn == 0) 0 else 1) Row { repeat(columns) { column -> Column { val base = column * itemsPerColumn val end = minOf(base + itemsPerColumn, items.size) for (index in base until end) { movableItems[index]() } } } }
| Parameters | |
|---|---|
content: @Composable R.(P) -> Unit |
The composable lambda to convert into a state tracking lambda. |
| Returns | |
|---|---|
@Composable R.(P) -> Unit |
A tracking composable lambda |
movableContentWithReceiverOf
@RememberInComposition
fun <R : Any?, P1 : Any?, P2 : Any?> movableContentWithReceiverOf(
content: @Composable R.(P1, P2) -> Unit
): @Composable R.(P1, P2) -> Unit
Convert a lambda with a receiver into one that moves the remembered state and nodes created in a previous call to the new location it is called.
Tracking compositions can be used to produce a composable that moves its content between a row and a column based on a parameter, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val movableContent = remember(content) { movableContentOf(content) } if (vertical) { Column { movableContent() } } else { Row { movableContent() } }
Or they can be used to ensure the composition state tracks with a model as moves in the layout, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.Composable import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val itemMap = remember { mutableMapOf<Item, @Composable () -> Unit>() } val movableItems = items.map { item -> itemMap.getOrPut(item) { movableContentOf { ItemView(item) } } } val itemsPerColumn = 10 val columns = items.size / itemsPerColumn + (if (items.size % itemsPerColumn == 0) 0 else 1) Row { repeat(columns) { column -> Column { val base = column * itemsPerColumn val end = minOf(base + itemsPerColumn, items.size) for (index in base until end) { movableItems[index]() } } } }
| Parameters | |
|---|---|
content: @Composable R.(P1, P2) -> Unit |
The composable lambda to convert into a state tracking lambda. |
| Returns | |
|---|---|
@Composable R.(P1, P2) -> Unit |
A tracking composable lambda |
movableContentWithReceiverOf
@RememberInComposition
fun <R : Any?, P1 : Any?, P2 : Any?, P3 : Any?> movableContentWithReceiverOf(
content: @Composable R.(P1, P2, P3) -> Unit
): @Composable R.(P1, P2, P3) -> Unit
Convert a lambda with a receiver into one that moves the remembered state and nodes created in a previous call to the new location it is called.
Tracking compositions can be used to produce a composable that moves its content between a row and a column based on a parameter, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val movableContent = remember(content) { movableContentOf(content) } if (vertical) { Column { movableContent() } } else { Row { movableContent() } }
Or they can be used to ensure the composition state tracks with a model as moves in the layout, such as,
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.runtime.Composable import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember val itemMap = remember { mutableMapOf<Item, @Composable () -> Unit>() } val movableItems = items.map { item -> itemMap.getOrPut(item) { movableContentOf { ItemView(item) } } } val itemsPerColumn = 10 val columns = items.size / itemsPerColumn + (if (items.size % itemsPerColumn == 0) 0 else 1) Row { repeat(columns) { column -> Column { val base = column * itemsPerColumn val end = minOf(base + itemsPerColumn, items.size) for (index in base until end) { movableItems[index]() } } } }
| Parameters | |
|---|---|
content: @Composable R.(P1, P2, P3) -> Unit |
The composable lambda to convert into a state tracking lambda. |
| Returns | |
|---|---|
@Composable R.(P1, P2, P3) -> Unit |
A tracking composable lambda |
mutableDoubleStateOf
@StateFactoryMarker
fun mutableDoubleStateOf(value: Double): MutableDoubleState
Return a new MutableDoubleState initialized with the passed in value
The MutableDoubleState class is a single value holder whose reads and writes are observed by Compose. Additionally, writes to it are transacted as part of the Snapshot system. On the JVM, values are stored in memory as the primitive double type, avoiding the autoboxing that occurs when using MutableState<Double>.
| Parameters | |
|---|---|
value: Double |
the initial value for the |
mutableFloatStateOf
@StateFactoryMarker
fun mutableFloatStateOf(value: Float): MutableFloatState
Return a new MutableFloatState initialized with the passed in value
The MutableFloatState class is a single value holder whose reads and writes are observed by Compose. Additionally, writes to it are transacted as part of the Snapshot system. On the JVM, values are stored in memory as the primitive float type, avoiding the autoboxing that occurs when using MutableState<Float>.
| Parameters | |
|---|---|
value: Float |
the initial value for the |
mutableIntStateOf
@StateFactoryMarker
fun mutableIntStateOf(value: Int): MutableIntState
Return a new MutableIntState initialized with the passed in value
The MutableIntState class is a single value holder whose reads and writes are observed by Compose. Additionally, writes to it are transacted as part of the Snapshot system. On the JVM, values are stored in memory as the primitive int type, avoiding the autoboxing that occurs when using MutableState<Int>.
| Parameters | |
|---|---|
value: Int |
the initial value for the |
mutableLongStateOf
@StateFactoryMarker
fun mutableLongStateOf(value: Long): MutableLongState
Return a new MutableLongState initialized with the passed in value
The MutableLongState class is a single value holder whose reads and writes are observed by Compose. Additionally, writes to it are transacted as part of the Snapshot system. On the JVM, values are stored in memory as the primitive long type, avoiding the autoboxing that occurs when using MutableState<Long>.
| Parameters | |
|---|---|
value: Long |
the initial value for the |
mutableStateListOf
@StateFactoryMarker
fun <T : Any?> mutableStateListOf(): SnapshotStateList<T>
Create a instance of MutableList
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @Composable fun Names() { var name by remember { mutableStateOf("user") } val names = remember { mutableStateListOf<String>() } Column { Row { BasicTextField(value = name, onValueChange = { name = it }) Button(onClick = { names.add(name) }) { Text("Add") } } Text("Added names:") Column { for (addedName in names) { Text(addedName) } } } }
mutableStateListOf
@StateFactoryMarker
fun <T : Any?> mutableStateListOf(vararg elements: T): SnapshotStateList<T>
Create an instance of MutableList
mutableStateMapOf
@StateFactoryMarker
fun <K : Any?, V : Any?> mutableStateMapOf(): SnapshotStateMap<K, V>
Create a instance of MutableMap
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @Composable fun NamesAndAges() { var name by remember { mutableStateOf("name") } var saying by remember { mutableStateOf("saying") } val sayings = remember { mutableStateMapOf( "Caesar" to "Et tu, Brute?", "Hamlet" to "To be or not to be", "Richard III" to "My kingdom for a horse", ) } Column { Row { BasicTextField(value = name, onValueChange = { name = it }) BasicTextField(value = saying, onValueChange = { saying = it }) Button(onClick = { sayings[name] = saying }) { Text("Add") } Button(onClick = { sayings.remove(name) }) { Text("Remove") } } Text("Sayings:") Column { for (entry in sayings) { Text("${entry.key} says '${entry.value}'") } } } }
| See also | |
|---|---|
mutableStateOf |
|
mutableMapOf |
|
MutableMap |
|
takeSnapshot |
mutableStateMapOf
@StateFactoryMarker
fun <K : Any?, V : Any?> mutableStateMapOf(vararg pairs: Pair<K, V>): SnapshotStateMap<K, V>
Create a instance of MutableMap
| See also | |
|---|---|
mutableStateOf |
|
mutableMapOf |
|
MutableMap |
|
takeSnapshot |
mutableStateOf
@StateFactoryMarker
fun <T : Any?> mutableStateOf(
value: T,
policy: SnapshotMutationPolicy<T> = structuralEqualityPolicy()
): MutableState<T>
Return a new MutableState initialized with the passed in value
The MutableState class is a single value holder whose reads and writes are observed by Compose. Additionally, writes to it are transacted as part of the Snapshot system.
import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember val count = remember { mutableStateOf(0) } Text(text = "You clicked ${count.value} times") Button(onClick = { count.value++ }) { Text("Click me") }
import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember val (count, setCount) = remember { mutableStateOf(0) } Text(text = "You clicked $count times") Button(onClick = { setCount(count + 1) }) { Text("Click me") }
import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @Composable fun observeUser(userId: Int): User? { val user = remember(userId) { mutableStateOf<User?>(null) } DisposableEffect(userId) { val subscription = UserAPI.subscribeToUser(userId) { user.value = it } onDispose { subscription.unsubscribe() } } return user.value }
import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @Composable fun LoginScreen() { var username by remember { mutableStateOf("user") } var password by remember { mutableStateOf("pass") } fun login() = Api.login(username, password) BasicTextField(value = username, onValueChange = { username = it }) BasicTextField(value = password, onValueChange = { password = it }) Button(onClick = { login() }) { Text("Login") } }
| Parameters | |
|---|---|
value: T |
the initial value for the |
policy: SnapshotMutationPolicy<T> = structuralEqualityPolicy() |
a policy to controls how changes are handled in mutable snapshots. |
mutableStateSetOf
@StateFactoryMarker
fun <T : Any?> mutableStateSetOf(): SnapshotStateSet<T>
Create a instance of MutableSet
The returned set iteration order is in the order the items were inserted into the set.
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.selection.selectableGroup import androidx.compose.foundation.selection.toggleable import androidx.compose.material.Checkbox import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateSetOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.Role @Composable fun DaysForAlarm() { val days = remember { mutableStateSetOf<DayOfWeek>() } Column(Modifier.selectableGroup()) { DayOfWeek.entries.forEach { dayOfWeek -> Row( modifier = Modifier.toggleable( value = dayOfWeek in days, role = Role.Checkbox, onValueChange = { if (it) { days.add(dayOfWeek) } else { days.remove(dayOfWeek) } }, ) ) { Checkbox(checked = dayOfWeek in days, onCheckedChange = null) Text(text = dayOfWeek.name) } } } }
| See also | |
|---|---|
mutableStateOf |
|
mutableSetOf |
|
MutableSet |
|
takeSnapshot |
mutableStateSetOf
@StateFactoryMarker
fun <T : Any?> mutableStateSetOf(vararg elements: T): SnapshotStateSet<T>
Create an instance of MutableSet
The returned set iteration order is in the order the items were inserted into the set.
| See also | |
|---|---|
mutableStateOf |
|
mutableSetOf |
|
MutableSet |
|
takeSnapshot |
neverEqualPolicy
fun <T : Any?> neverEqualPolicy(): SnapshotMutationPolicy<T>
A policy never treat values of a MutableState as equivalent.
Setting MutableState.value will always be considered a change. When applying a MutableSnapshot that changes the state will always conflict with other snapshots that change the same state.
produceState
@Composable
fun <T : Any?> produceState(initialValue: T, producer: suspend ProduceStateScope<T>.() -> Unit): State<T>
Return an observable snapshot State that produces values over time without a defined data source.
producer is launched when produceState enters the composition and is cancelled when produceState leaves the composition. producer should use ProduceStateScope.value to set new values on the returned State.
The returned State conflates values; no change will be observable if ProduceStateScope.value is used to set a value that is equal to its old value, and observers may only see the latest value if several values are set in rapid succession.
produceState may be used to observe either suspending or non-suspending sources of external data, for example:
import androidx.compose.foundation.layout.Column import androidx.compose.runtime.produceState val uiState by produceState<UiState<List<Person>>>(UiState.Loading, viewModel) { viewModel.people.map { UiState.Data(it) }.collect { value = it } } when (val state = uiState) { is UiState.Loading -> Text("Loading...") is UiState.Data -> Column { for (person in state.data) { Text("Hello, ${person.name}") } } }
import androidx.compose.runtime.produceState val currentPerson by produceState<Person?>(null, viewModel) { val disposable = viewModel.registerPersonObserver { person -> value = person } awaitDispose { disposable.dispose() } }
produceState
@Composable
fun <T : Any?> produceState(initialValue: T, key1: Any?, producer: suspend ProduceStateScope<T>.() -> Unit): State<T>
Return an observable snapshot State that produces values over time from key1.
producer is launched when produceState enters the composition and is cancelled when produceState leaves the composition. If key1 changes, a running producer will be cancelled and re-launched for the new source. producer should use ProduceStateScope.value to set new values on the returned State.
The returned State conflates values; no change will be observable if ProduceStateScope.value is used to set a value that is equal to its old value, and observers may only see the latest value if several values are set in rapid succession.
produceState may be used to observe either suspending or non-suspending sources of external data, for example:
import androidx.compose.foundation.layout.Column import androidx.compose.runtime.produceState val uiState by produceState<UiState<List<Person>>>(UiState.Loading, viewModel) { viewModel.people.map { UiState.Data(it) }.collect { value = it } } when (val state = uiState) { is UiState.Loading -> Text("Loading...") is UiState.Data -> Column { for (person in state.data) { Text("Hello, ${person.name}") } } }
import androidx.compose.runtime.produceState val currentPerson by produceState<Person?>(null, viewModel) { val disposable = viewModel.registerPersonObserver { person -> value = person } awaitDispose { disposable.dispose() } }
produceState
@Composable
fun <T : Any?> produceState(
initialValue: T,
vararg keys: Any?,
producer: suspend ProduceStateScope<T>.() -> Unit
): State<T>
Return an observable snapshot State that produces values over time from keys.
producer is launched when produceState enters the composition and is cancelled when produceState leaves the composition. If keys change, a running producer will be cancelled and re-launched for the new source. producer should use ProduceStateScope.value to set new values on the returned State.
The returned State conflates values; no change will be observable if ProduceStateScope.value is used to set a value that is equal to its old value, and observers may only see the latest value if several values are set in rapid succession.
produceState may be used to observe either suspending or non-suspending sources of external data, for example:
import androidx.compose.foundation.layout.Column import androidx.compose.runtime.produceState val uiState by produceState<UiState<List<Person>>>(UiState.Loading, viewModel) { viewModel.people.map { UiState.Data(it) }.collect { value = it } } when (val state = uiState) { is UiState.Loading -> Text("Loading...") is UiState.Data -> Column { for (person in state.data) { Text("Hello, ${person.name}") } } }
import androidx.compose.runtime.produceState val currentPerson by produceState<Person?>(null, viewModel) { val disposable = viewModel.registerPersonObserver { person -> value = person } awaitDispose { disposable.dispose() } }
produceState
@Composable
fun <T : Any?> produceState(
initialValue: T,
key1: Any?,
key2: Any?,
producer: suspend ProduceStateScope<T>.() -> Unit
): State<T>
Return an observable snapshot State that produces values over time from key1 and key2.
producer is launched when produceState enters the composition and is cancelled when produceState leaves the composition. If key1 or key2 change, a running producer will be cancelled and re-launched for the new source. producer should use ProduceStateScope.value to set new values on the returned State.
The returned State conflates values; no change will be observable if ProduceStateScope.value is used to set a value that is equal to its old value, and observers may only see the latest value if several values are set in rapid succession.
produceState may be used to observe either suspending or non-suspending sources of external data, for example:
import androidx.compose.foundation.layout.Column import androidx.compose.runtime.produceState val uiState by produceState<UiState<List<Person>>>(UiState.Loading, viewModel) { viewModel.people.map { UiState.Data(it) }.collect { value = it } } when (val state = uiState) { is UiState.Loading -> Text("Loading...") is UiState.Data -> Column { for (person in state.data) { Text("Hello, ${person.name}") } } }
import androidx.compose.runtime.produceState val currentPerson by produceState<Person?>(null, viewModel) { val disposable = viewModel.registerPersonObserver { person -> value = person } awaitDispose { disposable.dispose() } }
produceState
@Composable
fun <T : Any?> produceState(
initialValue: T,
key1: Any?,
key2: Any?,
key3: Any?,
producer: suspend ProduceStateScope<T>.() -> Unit
): State<T>
Return an observable snapshot State that produces values over time from key1, key2 and key3.
producer is launched when produceState enters the composition and is cancelled when produceState leaves the composition. If key1, key2 or key3 change, a running producer will be cancelled and re-launched for the new source. [producer should use ProduceStateScope.value to set new values on the returned State.
The returned State conflates values; no change will be observable if ProduceStateScope.value is used to set a value that is equal to its old value, and observers may only see the latest value if several values are set in rapid succession.
produceState may be used to observe either suspending or non-suspending sources of external data, for example:
import androidx.compose.foundation.layout.Column import androidx.compose.runtime.produceState val uiState by produceState<UiState<List<Person>>>(UiState.Loading, viewModel) { viewModel.people.map { UiState.Data(it) }.collect { value = it } } when (val state = uiState) { is UiState.Loading -> Text("Loading...") is UiState.Data -> Column { for (person in state.data) { Text("Hello, ${person.name}") } } }
import androidx.compose.runtime.produceState val currentPerson by produceState<Person?>(null, viewModel) { val disposable = viewModel.registerPersonObserver { person -> value = person } awaitDispose { disposable.dispose() } }
referentialEqualityPolicy
fun <T : Any?> referentialEqualityPolicy(): SnapshotMutationPolicy<T>
A policy to treat values of a MutableState as equivalent if they are referentially (===) equal.
Setting MutableState.value to its current referentially (===) equal value is not considered a change. When applying a MutableSnapshot, if the snapshot changes the value to the equivalent value the parent snapshot has is not considered a conflict.
remember
@Composable
inline fun <T : Any?> remember(crossinline calculation: @DisallowComposableCalls () -> T): T
Remember the value produced by calculation. calculation will only be evaluated during the composition. Recomposition will always return the value produced by composition.
remember
@Composable
inline fun <T : Any?> remember(
key1: Any?,
crossinline calculation: @DisallowComposableCalls () -> T
): T
Remember the value returned by calculation if key1 compares equal (==) to the value it had in the previous composition, otherwise produce and remember a new value by calling calculation.
remember
@Composable
inline fun <T : Any?> remember(
vararg keys: Any?,
crossinline calculation: @DisallowComposableCalls () -> T
): T
Remember the value returned by calculation if all values of keys are equal (==) to the values they had in the previous composition, otherwise produce and remember a new value by calling calculation.
remember
@Composable
inline fun <T : Any?> remember(
key1: Any?,
key2: Any?,
crossinline calculation: @DisallowComposableCalls () -> T
): T
Remember the value returned by calculation if key1 and key2 are equal (==) to the values they had in the previous composition, otherwise produce and remember a new value by calling calculation.
remember
@Composable
inline fun <T : Any?> remember(
key1: Any?,
key2: Any?,
key3: Any?,
crossinline calculation: @DisallowComposableCalls () -> T
): T
Remember the value returned by calculation if key1, key2 and key3 are equal (==) to values they had in the previous composition, otherwise produce and remember a new value by calling calculation.
rememberCompositionContext
@Composable
fun rememberCompositionContext(): CompositionContext
An Effect to construct a CompositionContext at the current point of composition. This can be used to run a separate composition in the context of the current one, preserving CompositionLocals and propagating invalidations. When this call leaves the composition, the context is invalidated.
rememberCoroutineScope
@Composable
inline fun rememberCoroutineScope(
crossinline getContext: @DisallowComposableCalls () -> CoroutineContext = { EmptyCoroutineContext }
): CoroutineScope
Return a CoroutineScope bound to this point in the composition using the optional CoroutineContext provided by getContext. getContext will only be called once and the same CoroutineScope instance will be returned across recompositions.
This scope will be cancelled when this call leaves the composition. The CoroutineContext returned by getContext may not contain a Job as this scope is considered to be a child of the composition.
The default dispatcher of this scope if one is not provided by the context returned by getContext will be the applying dispatcher of the composition's Recomposer.
Use this scope to launch jobs in response to callback events such as clicks or other user interaction where the response to that event needs to unfold over time and be cancelled if the composable managing that process leaves the composition. Jobs should never be launched into any coroutine scope as a side effect of composition itself. For scoped ongoing jobs initiated by composition, see LaunchedEffect.
This function will not throw if preconditions are not met, as composable functions do not yet fully support exceptions. Instead the returned scope's CoroutineScope.coroutineContext will contain a failed Job with the associated exception and will not be capable of launching child jobs.
rememberUpdatedState
@Composable
fun <T : Any?> rememberUpdatedState(newValue: T): State<T>
remember a mutableStateOf and update its value to newValue on each recomposition of the rememberUpdatedState call.
rememberUpdatedState should be used when parameters or values computed during composition are referenced by a long-lived lambda or object expression. Recomposition will update the resulting State without recreating the long-lived lambda or object, allowing that object to persist without cancelling and resubscribing, or relaunching a long-lived operation that may be expensive or prohibitive to recreate and restart. This may be common when working with DisposableEffect or LaunchedEffect, for example:
import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState @Composable fun EventHandler(dispatcher: Dispatcher, onEvent: () -> Unit) { val currentOnEvent by rememberUpdatedState(onEvent) // Event handlers are ordered and a new onEvent should not cause us to re-register, // losing our position in the dispatcher. DisposableEffect(dispatcher) { val disposable = dispatcher.addListener { // currentOnEvent will always refer to the latest onEvent function that // the EventHandler was recomposed with currentOnEvent() } onDispose { disposable.dispose() } } }
LaunchedEffects often describe state machines that should not be reset and restarted if a parameter or event callback changes, but they should have the current value available when needed. For example:
import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState @Composable fun NotificationHost(state: NotificationState, onTimeout: (Notification) -> Unit) { val currentOnTimeout by rememberUpdatedState(onTimeout) state.currentNotification?.let { currentNotification -> LaunchedEffect(currentNotification) { // We should not restart this delay if onTimeout changes, but we want to call // the onTimeout we were last recomposed with when it completes. delay(NotificationTimeout) currentOnTimeout(currentNotification) } } // ... }
By using rememberUpdatedState a composable function can update these operations in progress.
simulateHotReload
@TestOnly
fun simulateHotReload(context: Any): Unit
Simulates hot reload of all current compositions by disposing all composed content and restarting compositions. Calling this method switches recomposer into hot reload mode. Test-only API, not for use in production.
| Parameters | |
|---|---|
context: Any |
context for disposal. |
snapshotFlow
fun <T : Any?> snapshotFlow(block: () -> T): Flow<T>
Create a Flow from observable Snapshot state. (e.g. state holders returned by mutableStateOf.)
snapshotFlow creates a Flow that runs block when collected and emits the result, recording any snapshot state that was accessed. While collection continues, if a new Snapshot is applied that changes state accessed by block, the flow will run block again, re-recording the snapshot state that was accessed. If the result of block is not equal to the previous result, the flow will emit that new result. (This behavior is similar to that of Flow.distinctUntilChanged.) Collection will continue indefinitely unless it is explicitly cancelled or limited by the use of other Flow operators.
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.snapshotFlow import androidx.compose.runtime.snapshots.Snapshot // Define Snapshot state objects var greeting by mutableStateOf("Hello") var person by mutableStateOf("Adam") // ... // Create a flow that will emit whenever our person-specific greeting changes val greetPersonFlow = snapshotFlow { "$greeting, $person" } // ... val collectionScope: CoroutineScope = TODO("Use your scope here") // Collect the flow and offer greetings! collectionScope.launch { greetPersonFlow.collect { flowGreeting -> println(flowGreeting) } } // ... // Change snapshot state; greetPersonFlow will emit a new greeting Snapshot.withMutableSnapshot { greeting = "Ahoy" person = "Sean" }
block is run in a read-only Snapshot and may not modify snapshot data. If block attempts to modify snapshot data, flow collection will fail with IllegalStateException.
block may run more than once for equal sets of inputs or only once after many rapid snapshot changes; it should be idempotent and free of side effects.
When working with Snapshot state it is useful to keep the distinction between events and state in mind. snapshotFlow models snapshot changes as events, but events cannot be effectively modeled as observable state. Observable state is a lossy compression of the events that produced that state.
An observable event happens at a point in time and is discarded. All registered observers at the time the event occurred are notified. All individual events in a stream are assumed to be relevant and may build on one another; repeated equal events have meaning and therefore a registered observer must observe all events without skipping.
Observable state raises change events when the state changes from one value to a new, unequal value. State change events are conflated; only the most recent state matters. Observers of state changes must therefore be idempotent; given the same state value the observer should produce the same result. It is valid for a state observer to both skip intermediate states as well as run multiple times for the same state and the result should be the same.
sourceInformation
@ComposeCompilerApi
fun sourceInformation(composer: Composer, sourceInformation: String): Unit
A Compose internal function. DO NOT call directly.
Records source information that can be used for tooling to determine the source location of the corresponding composable function. By default, this function is declared as having no side-effects. It is safe for code shrinking tools (such as R8 or ProGuard) to remove it.
sourceInformationMarkerEnd
@ComposeCompilerApi
fun sourceInformationMarkerEnd(composer: Composer): Unit
A Compose internal function. DO NOT call directly.
Records the end of a source information marker that can be used for tooling to determine the source location of the corresponding composable function that otherwise don't require tracking information such as ReadOnlyComposable functions. By default, this function is declared as having no side-effects. It is safe for code shrinking tools (such as R8 or ProGuard) to remove it.
Important that both sourceInformationMarkerStart and sourceInformationMarkerEnd are removed together or both kept. Removing only one will cause incorrect runtime behavior.
sourceInformationMarkerStart
@ComposeCompilerApi
fun sourceInformationMarkerStart(
composer: Composer,
key: Int,
sourceInformation: String
): Unit
A Compose internal function. DO NOT call directly.
Records the start of a source information marker that can be used for tooling to determine the source location of the corresponding composable function that otherwise don't require tracking information such as ReadOnlyComposable functions. By default, this function is declared as having no side-effects. It is safe for code shrinking tools (such as R8 or ProGuard) to remove it.
Important that both sourceInformationMarkerStart and sourceInformationMarkerEnd are removed together or both kept. Removing only one will cause incorrect runtime behavior.
staticCompositionLocalOf
fun <T : Any?> staticCompositionLocalOf(defaultFactory: () -> T): ProvidableCompositionLocal<T>
Create a CompositionLocal key that can be provided using CompositionLocalProvider.
Unlike compositionLocalOf, reads of a staticCompositionLocalOf are not tracked by the composer and changing the value provided in the CompositionLocalProvider call will cause the entirety of the content to be recomposed instead of just the places where in the composition the local value is used. This lack of tracking, however, makes a staticCompositionLocalOf more efficient when the value provided is highly unlikely to or will never change. For example, the android context, font loaders, or similar shared values, are unlikely to change for the components in the content of a the CompositionLocalProvider and should consider using a staticCompositionLocalOf. A color, or other theme like value, might change or even be animated therefore a compositionLocalOf should be used.
staticCompositionLocalOf creates a ProvidableCompositionLocal which can be used in a a call to CompositionLocalProvider. Similar to MutableList vs. List, if the key is made public as CompositionLocal instead of ProvidableCompositionLocal, it can be read using CompositionLocal.current but not re-provided.
| Parameters | |
|---|---|
defaultFactory: () -> T |
a value factory to supply a value when a value is not provided. This factory is called when no value is provided through a |
| See also | |
|---|---|
CompositionLocal |
|
compositionLocalOf |
structuralEqualityPolicy
fun <T : Any?> structuralEqualityPolicy(): SnapshotMutationPolicy<T>
A policy to treat values of a MutableState as equivalent if they are structurally (==) equal.
Setting MutableState.value to its current structurally (==) equal value is not considered a change. When applying a MutableSnapshot, if the snapshot changes the value to the equivalent value the parent snapshot has is not considered a conflict.
traceEventEnd
@ComposeCompilerApi
fun traceEventEnd(): Unit
Internal tracing API.
Should be called without thread synchronization with occasional information loss.
traceEventStart
@ComposeCompilerApi
fun traceEventStart(key: Int, dirty1: Int, dirty2: Int, info: String): Unit
Internal tracing API.
Should be called without thread synchronization with occasional information loss.
| Parameters | |
|---|---|
key: Int |
is a group key generated by the compiler plugin for the function being traced. This key is unique the function. |
dirty1: Int |
$dirty metadata: forced-recomposition and function parameters 1..10 if present |
dirty2: Int |
$dirty2 metadata: forced-recomposition and function parameters 11..20 if present |
info: String |
is a user displayable string that describes the function for which this is the start event. |
withCompositionLocal
@Composable
inline fun <T : Any?> withCompositionLocal(
value: ProvidedValue<*>,
content: @Composable () -> T
): T
withCompositionLocal binds value to ProvidableCompositionLocal key and returns the result produced by the content lambda. Use with non-unit returning content lambdas or else use CompositionLocalProvider. Reading the CompositionLocal using CompositionLocal.current will return the value provided in CompositionLocalProvider's value parameter for all composable functions called directly or indirectly in the content lambda.
withCompositionLocals
@Composable
inline fun <T : Any?> withCompositionLocals(
vararg values: ProvidedValue<*>,
content: @Composable () -> T
): T
withCompositionLocals binds values to ProvidableCompositionLocal key and returns the result produced by the content lambda. Use with non-unit returning content lambdas or else use CompositionLocalProvider. Reading the CompositionLocal using CompositionLocal.current will return the values provided in CompositionLocalProvider's values parameter for all composable functions called directly or indirectly in the content lambda.
withFrameMillis
suspend fun <R : Any?> withFrameMillis(onFrame: (frameTimeMillis: Long) -> R): R
Suspends until a new frame is requested, immediately invokes onFrame with the frame time in milliseconds in the calling context of frame dispatch, then resumes with the result from onFrame.
frameTimeMillis should be used when calculating animation time deltas from frame to frame as it may be normalized to the target time for the frame, not necessarily a direct, "now" value.
The time base of the value provided by MonotonicFrameClock.withFrameMillis is implementation defined. Time values provided are monotonically increasing; after a call to withFrameMillis completes it must not provide a smaller value for a subsequent call.
This function will invoke MonotonicFrameClock.withFrameNanos using the calling CoroutineContext's MonotonicFrameClock and will throw an IllegalStateException if one is not present in the CoroutineContext.
withFrameNanos
suspend fun <R : Any?> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R): R
Suspends until a new frame is requested, immediately invokes onFrame with the frame time in nanoseconds in the calling context of frame dispatch, then resumes with the result from onFrame.
frameTimeNanos should be used when calculating animation time deltas from frame to frame as it may be normalized to the target time for the frame, not necessarily a direct, "now" value.
The time base of the value provided by withFrameNanos is implementation defined. Time values provided are strictly monotonically increasing; after a call to withFrameNanos completes it must not provide the same value again for a subsequent call.
This function will invoke MonotonicFrameClock.withFrameNanos using the calling CoroutineContext's MonotonicFrameClock and will throw an IllegalStateException if one is not present in the CoroutineContext.
withRunningRecomposer
suspend fun <R : Any?> withRunningRecomposer(block: suspend CoroutineScope.(recomposer: Recomposer) -> R): R
Runs block with a new, active Recomposer applying changes in the calling CoroutineContext. The Recomposer will be closed after block returns. withRunningRecomposer will return once the Recomposer is Recomposer.State.ShutDown and all child jobs launched by block have joined.
Extension functions
asDoubleState
fun State<Double>.asDoubleState(): DoubleState
Converts a State<Double> (as in, a State of boxed Doubles) into a primitive-backed Double. The state will be automatically unboxed to the required primitive type. The returned state is read-only. The returned state will mirror the values of the base state and apply updates in the same way as the receiver defines.
On the JVM, this conversion does not avoid the autoboxing that Double attempts to escape, but instead is intended to allow interoperability between components that use either representation of a state of type Double.
asFloatState
fun State<Float>.asFloatState(): FloatState
Converts a State<Float> (as in, a State of boxed Floats) into a primitive-backed Float. The state will be automatically unboxed to the required primitive type. The returned state is read-only. The returned state will mirror the values of the base state and apply updates in the same way as the receiver defines.
On the JVM, this conversion does not avoid the autoboxing that Float attempts to escape, but instead is intended to allow interoperability between components that use either representation of a state of type Float.
asIntState
fun State<Int>.asIntState(): IntState
Converts a State<Int> (as in, a State of boxed Ints) into a primitive-backed IntState. The state will be automatically unboxed to the required primitive type. The returned state is read-only. The returned state will mirror the values of the base state and apply updates in the same way as the receiver defines.
On the JVM, this conversion does not avoid the autoboxing that IntState attempts to escape, but instead is intended to allow interoperability between components that use either representation of a state of type Int.
asLongState
fun State<Long>.asLongState(): LongState
Converts a State<Long> (as in, a State of boxed Longs) into a primitive-backed LongState. The state will be automatically unboxed to the required primitive type. The returned state is read-only. The returned state will mirror the values of the base state and apply updates in the same way as the receiver defines.
On the JVM, this conversion does not avoid the autoboxing that LongState attempts to escape, but instead is intended to allow interoperability between components that use either representation of a state of type Long.
cache
@ComposeCompilerApi
inline fun <T : Any?> Composer.cache(
invalid: Boolean,
block: @DisallowComposableCalls () -> T
): T
A Compose compiler plugin API. DO NOT call directly.
Cache, that is remember, a value in the composition data of a composition. This is used to implement remember and used by the compiler plugin to generate more efficient calls to remember when it determines these optimizations are safe.
collectAsState
@Composable
fun <T : Any?> StateFlow<T>.collectAsState(
context: CoroutineContext = EmptyCoroutineContext
): State<T>
Collects values from this StateFlow and represents its latest value via State. The StateFlow.value is used as an initial value. Every time there would be new value posted into the StateFlow the returned State will be updated causing recomposition of every State.value usage.
import androidx.compose.material.Text import androidx.compose.runtime.collectAsState val value: String by stateFlow.collectAsState() Text("Value is $value")
| Parameters | |
|---|---|
context: CoroutineContext = EmptyCoroutineContext |
|
collectAsState
@Composable
fun <T : R, R : Any?> Flow<T>.collectAsState(
initial: R,
context: CoroutineContext = EmptyCoroutineContext
): State<R>
Collects values from this Flow and represents its latest value via State. Every time there would be new value posted into the Flow the returned State will be updated causing recomposition of every State.value usage.
import androidx.compose.material.Text import androidx.compose.runtime.collectAsState val value: String by flow.collectAsState("initial") Text("Value is $value")
| Parameters | |
|---|---|
initial: R |
the value of the state will have until the first flow value is emitted. |
context: CoroutineContext = EmptyCoroutineContext |
|
getValue
inline operator fun DoubleState.getValue(thisObj: Any?, property: KProperty<*>): Double
Permits property delegation of vals using by for DoubleState.
getValue
inline operator fun FloatState.getValue(thisObj: Any?, property: KProperty<*>): Float
Permits property delegation of vals using by for FloatState.
getValue
inline operator fun IntState.getValue(thisObj: Any?, property: KProperty<*>): Int
Permits property delegation of vals using by for IntState.
getValue
inline operator fun LongState.getValue(thisObj: Any?, property: KProperty<*>): Long
Permits property delegation of vals using by for LongState.
getValue
inline operator fun <T : Any?> State<T>.getValue(thisObj: Any?, property: KProperty<*>): T
Permits property delegation of vals using by for State.
import androidx.compose.foundation.layout.Row import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.State // Composable function that manages a subscription to a data source, returning it as State @Composable fun observeSampleData(): State<String> = TODO() // Subscription is managed here, but currentValue is not read yet val currentValue by observeSampleData() Row { // This scope will recompose when currentValue changes Text("Data: $currentValue") }
setValue
inline operator fun MutableDoubleState.setValue(
thisObj: Any?,
property: KProperty<*>,
value: Double
): Unit
Permits property delegation of vars using by for MutableDoubleState.
setValue
inline operator fun MutableFloatState.setValue(
thisObj: Any?,
property: KProperty<*>,
value: Float
): Unit
Permits property delegation of vars using by for MutableFloatState.
setValue
inline operator fun MutableIntState.setValue(thisObj: Any?, property: KProperty<*>, value: Int): Unit
Permits property delegation of vars using by for MutableIntState.
setValue
inline operator fun MutableLongState.setValue(
thisObj: Any?,
property: KProperty<*>,
value: Long
): Unit
Permits property delegation of vars using by for MutableLongState.
setValue
inline operator fun <T : Any?> MutableState<T>.setValue(
thisObj: Any?,
property: KProperty<*>,
value: T
): Unit
Permits property delegation of vars using by for MutableState.
import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember var count by remember { mutableStateOf(0) } Text(text = "You clicked $count times") Button(onClick = { count = count + 1 }) { Text("Click me") }
toLong
fun CompositeKeyHashCode.toLong(): Long
Converts a CompositeKeyHashCode to a 64-bit Long. This may be higher precision than the underlying type.
toMutableStateList
fun <T : Any?> Collection<T>.toMutableStateList(): SnapshotStateList<T>
Create an instance of MutableList
toMutableStateMap
fun <K : Any?, V : Any?> Iterable<Pair<K, V>>.toMutableStateMap(): SnapshotStateMap<K, V>
Create an instance of MutableMap
toString
fun CompositeKeyHashCode.toString(radix: Int): String
Returns a String representation of a CompositeKeyHashCode with the specified radix.
| Throws | |
|---|---|
kotlin.IllegalArgumentException |
when |
withFrameMillis
suspend inline fun <R : Any?> MonotonicFrameClock.withFrameMillis(
crossinline onFrame: (frameTimeMillis: Long) -> R
): R
Suspends until a new frame is requested, immediately invokes onFrame with the frame time in milliseconds in the calling context of frame dispatch, then resumes with the result from onFrame.
frameTimeMillis should be used when calculating animation time deltas from frame to frame as it may be normalized to the target time for the frame, not necessarily a direct, "now" value.
The time base of the value provided by MonotonicFrameClock.withFrameMillis is implementation defined. Time values provided are monotonically increasing; after a call to withFrameMillis completes it must not provide a smaller value for a subsequent call.
Top-level properties
DefaultMonotonicFrameClock
val DefaultMonotonicFrameClock: MonotonicFrameClock
The MonotonicFrameClock used by withFrameNanos and withFrameMillis if one is not present in the calling kotlin.coroutines.CoroutineContext.
This value is no longer used by compose runtime.
EmptyCompositeKeyHashCode
val EmptyCompositeKeyHashCode: CompositeKeyHashCode
An empty CompositeKeyHashCode, equivalent to hashing no content. This is not necessarily the same as the hash at the root of a composition. This is an effective default value in the absence of a hash from currentCompositeKeyHashCode.
currentCompositeKeyHash
val currentCompositeKeyHash: Int
This a hash value used to coordinate map externally stored state to the composition. For example, this is used by saved instance state to preserve state across activity lifetime boundaries.
This value is likely to be unique but is not guaranteed unique. There are known cases, such as for loops without a key, where the runtime does not have enough information to make the compound key hash unique.
| See also | |
|---|---|
currentCompositeKeyHashCode |
currentCompositeKeyHashCode
val currentCompositeKeyHashCode: CompositeKeyHashCode
A higher-precision variation of currentCompositeKeyHash used to map externally stored state to the composition. By stepping up to a Long, this variation of the key hash is exponentially less likely to experience a collision.
In practice, because the hash is not perfectly distributed and because there are situations where the runtime can't uniquely identify certain repeated content, collisions are still possible. This higher precision does, however, afford more confidence in the assumption that an arbitrarily sized composition hierarchy will not experience two unrelated groups having the same key hash.
currentCompositionContext
@InternalComposeApi
val currentCompositionContext: CompositionContext
Returns the CompositionContext associated for the current composer.
This API is exposed for internal usages only. It should not be invoked outside of the Compose Runtime
currentCompositionLocalContext
val currentCompositionLocalContext: CompositionLocalContext
Returns the current CompositionLocalContext which contains all CompositionLocal's in the current composition and their values provided by CompositionLocalProvider's. This context can be used to pass locals to another composition via CompositionLocalProvider. That is usually needed if another composition is not a subcomposition of the current one.
currentRecomposeScope
val currentRecomposeScope: RecomposeScope
Returns an object which can be used to invalidate the current scope at this point in composition. This object can be used to manually cause recompositions.
Extension properties
monotonicFrameClock
@ExperimentalComposeApi
val CoroutineContext.monotonicFrameClock: MonotonicFrameClock
Returns the MonotonicFrameClock for this CoroutineContext or throws IllegalStateException if one is not present.
recomposeCoroutineContext
@ExperimentalComposeApi
val ControlledComposition.recomposeCoroutineContext: CoroutineContext
The CoroutineContext that should be used to perform concurrent recompositions of this ControlledComposition when used in an environment supporting concurrent composition.
See Recomposer.runRecomposeConcurrentlyAndApplyChanges as an example of configuring such an environment.