CompositionLocal in Jetpack Compose
CompositionLocal in Jetpack Compose
CompositionLocal is a mechanism in Jetpack Compose for passing data implicitly down the composition tree without threading it through every composable function as a parameter. It provides scoped access to values like themes, configurations, and platform dependencies that many composables need but few should explicitly accept. By the end of this lesson, you will be able to:
- Explain how
CompositionLocalpropagates values through the composition tree. - Distinguish between
compositionLocalOfandstaticCompositionLocalOf. - Provide and consume
CompositionLocalvalues correctly. - Identify when
CompositionLocalis appropriate and when direct parameters are better.
Defining a CompositionLocal
You create a CompositionLocal using either compositionLocalOf or staticCompositionLocalOf. Both require a default value factory that is used when no provider is found in the composition tree:
val LocalUserName = compositionLocalOf { "Guest" }
The naming convention uses the Local prefix to signal that the value is provided through the composition tree rather than passed as a parameter. The default value is returned when a composable reads the CompositionLocal but no ancestor has provided a value through CompositionLocalProvider.
Providing Values
Use CompositionLocalProvider to supply a value within a specific scope. Any descendant composable within that scope can read the provided value:
@Composable
fun GreetingScreen() {
CompositionLocalProvider(
LocalUserName provides "skydoves"
) {
UserGreeting()
}
}
@Composable
fun UserGreeting() {
val userName = LocalUserName.current
Text("Hello, $userName!")
}
UserGreeting reads LocalUserName.current without receiving it as a parameter. If GreetingScreen did not provide a value, the default "Guest" from the definition would be used instead.
Values provided through CompositionLocalProvider are scoped to the composable subtree defined by the trailing lambda. Outside that scope, the previous value (or the default) applies. This scoping mechanism allows different parts of the tree to see different values for the same CompositionLocal.
compositionLocalOf vs. staticCompositionLocalOf
The two factory functions differ in how they handle recomposition when the provided value changes:
compositionLocalOf: Tracks which composables read the value. When the provided value changes, only the composables that actually called.currentrecompose. This is efficient when the value changes occasionally and only a few composables consume it.
This interview continues for subscribers
Subscribe to Dove Letter for full access to exclusive interviews about Android and Kotlin development.
Become a Sponsor