CompositionLocal
public sealed class CompositionLocal<T>(defaultFactory: () -> T)
Compose passes data through the composition tree explicitly through means of parameters to composable functions. This is often times the simplest and best way to have data flow through the tree.
Sometimes this model can be cumbersome or break down for data that is needed by lots of
components, or when components need to pass data between one another but keep that implementation
detail private. For these cases, CompositionLocal
s can be used as an implicit way to have data
flow through a composition.
CompositionLocal
s by their nature are hierarchical. They make sense when the value of the
CompositionLocal
needs to be scoped to a particular sub-hierarchy of the composition.
One must create a CompositionLocal
instance, which can be referenced by the consumers
statically. CompositionLocal
instances themselves hold no data, and can be thought of as a
type-safe identifier for the data being passed down a tree. CompositionLocal
factory functions
take a single parameter: a factory to create a default value in cases where a CompositionLocal
is used without a Provider. If this is a situation you would rather not handle, you can throw an
error in this factory.
Somewhere up the tree, a CompositionLocalProvider
component can be used, which provides a value
for the CompositionLocal
. This would often be at the "root" of a tree, but could be anywhere,
and can also be used in multiple places to override the provided value for a sub-tree.
Intermediate components do not need to know about the CompositionLocal
value, and can have zero
dependencies on it. For example, SomeScreen
might look like this:
Finally, a component that wishes to consume the CompositionLocal
value can use the current
property of the CompositionLocal
key which returns the current value of the CompositionLocal
,
and subscribes the component to changes of it.
Code Examples
createCompositionLocal
fun createCompositionLocal() {
val ActiveUser = compositionLocalOf<User> { error("No active user found!") }
}
compositionLocalProvider
fun compositionLocalProvider() {
@Composable
fun App(user: User) {
CompositionLocalProvider(ActiveUser provides user) { SomeScreen() }
}
}
someScreenSample
fun someScreenSample() {
@Composable
fun SomeScreen() {
UserPhoto()
}
}
consumeCompositionLocal
fun consumeCompositionLocal() {
@Composable
fun UserPhoto() {
val user = ActiveUser.current
ProfileIcon(src = user.profilePhotoUrl)
}
}