— Jetpack Compose, Android, CompositionLocal — 1 min read
Jetpack Compose simplifies Android UI development by using a declarative approach, but managing data flow across the UI hierarchy can be challenging. CompositionLocal comes to the rescue by allowing you to pass data implicitly through the composition - making data access easy and reducing boilerplate.
CompositionLocal is a powerful feature in Jetpack Compose that enables implicit data flow down the UI tree. It's ideal for sharing data that many components within your app might need access to, such as theming information (colors, typography, etc.).
Implementing CompositionLocal involves three main steps: defining, providing, and consuming the CompositionLocal.
To define a CompositionLocal, decide on the type of data you want to pass down. Here's an example of defining a CompositionLocal for theme settings:
1import androidx.compose.runtime.compositionLocalOf2import androidx.compose.ui.graphics.Color3
4data class ThemeSettings(val primaryColor: Color, val accentColor: Color)5
6// Define this as a global value7val LocalThemeSettings = compositionLocalOf { ThemeSettings(Color.Black, Color.White) }
After defining, you need to provide a value for your CompositionLocal at a higher level in your UI tree. This is typically done using the CompositionLocalProvider
:
1import androidx.compose.material.MaterialTheme2import androidx.compose.runtime.Composable3import androidx.compose.ui.graphics.Color4
5@Composable6fun MyAppTheme(content: @Composable () -> Unit) {7 val customThemeSettings = ThemeSettings(Color.Blue, Color.Green)8 CompositionLocalProvider(LocalThemeSettings provides customThemeSettings) {9 MaterialTheme {10 content()11 }12 }13}
Finally, to consume the provided value anywhere in your UI tree, use the .current
property of your CompositionLocal:
1import androidx.compose.material.Text2import androidx.compose.runtime.Composable3
4@Composable5fun ThemedText(text: String) {6 val themeSettings = LocalThemeSettings.current7 Text(text = text, color = themeSettings.primaryColor)8}