You're reading for free via Jayant Kumar🇮🇳's Friend Link. Become a member to access the best of Medium.
Member-only story
Composition Local In Jetpack Compose.
In this article we will see Composition Local
in Jetpack Compose and also see when to use or not.
If I asked a question to you , how do you pass any data to child composable functions?
Well your answer will be , pass data in the child’s composable function parameter, That’s it .
But if i say, now you don’t need to pass any data explicitly in the child composable function parameter instead of that use Composition Local
.
So what Composition Local
does , without passing anything in the function parameter , you can use that object directly in the child composable function.
Predefined Composition Locals
Jetpack Compose provides multiple predefined composition Locals implementations that start with the word Local
.

The most popular or you heard is -
val context = LocalContext.current
here LocalContext
is a Composition Local which find the context of current screen through .current
.
The best part is now you don’t need to pass this context
variable in the child composable function’s parameter every time , you can directly use this val context = LocalContext.current
where ever you want.
@Composable
fun CopyTextFromClipBoard(
modifier: Modifier = Modifier
) {
val clipboardManager = LocalClipboardManager.current
val context = LocalContext.current
Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Button(onClick = {
clipboardManager.setText(AnnotatedString(context.getString(R.string.copy_text_from_clipboard)))
}) {
Text(text = stringResource(R.string.copy_text))
}
}
}
LocalClipboardManager.current
is used to copy text from clipboard.
val textStyle = LocalTextStyle.current //default typograyphy
Text(text = stringResource(R.string.hello), style = textStyle)
Through LocalTextStyle.currrent
, we can find the current / default typography.
There are lot more options in Predefined Composition Local
, you can use according to your requirements.
Creating Your Own CompositionLocals
There are two ways to create your own custom composition locals
- staticCompositionLocalOf()
- compositionLocalOf()
staticCompositionLocalOf()
When the value of your CompositionLocal
doesn’t change often, staticCompositionLocalOf()
is a good choice.
The value created with staticCompositionLocalOf
is immutable and cannot be modified once created.
Let’s create a custom textstyle which store some custom textstyle data , and see how to provide that data to child composables.
@Stable
class CustomTextStyle(
val fontSize: TextUnit,
val fontWeight: FontWeight,
val color: Color
)
First we created a class which will store above types of data.
val LocalCustomTextStyle = staticCompositionLocalOf<CustomTextStyle> {
error("No Parameter is available")
}
it’s a good practise to start with Local
when you are creating any composition local. staticCompositionLocalOf
will create a composition local and if no value is passed to CustomTextStyle
class then it will thrown an error.
object ProvideCustomTextStyleData {
val customTextStyle = CustomTextStyle(
fontSize = 30.sp,
fontWeight = FontWeight.W500,
color = Color.Blue
)
}
In the above code we passed some static data that will be using later.
@Composable
fun ChildComposable() {
val customTextStyle = LocalCustomTextStyle.current
Text(
text = stringResource(R.string.child_composable_function_using_composition_local), style = TextStyle(
color = customTextStyle.color,
fontSize = customTextStyle.fontSize,
fontWeight = customTextStyle.fontWeight
)
)
}
As you can see above you can use composition local
in this way LocalCustomTextStyle.current
to get the data.
But when you run this app , application will crash , because we added some static data above but didn’t tell composition local to use that data.
@Composable
fun CompositionLocalScreen(
modifier: Modifier
) {
CompositionLocalProvider(
LocalCustomTextStyle provides ProvideCustomTextStyleData.customTextStyle,
) {
ChildComposable()
}
}
CompositionLocalProvider
function takes varargs
, you can pass as much as custom composition locals
there separated by ,
(comma). we can provide the data with provides
infix operator
Here whatever child composable function comes under CompositionLocalProvider
can use that customTextStyle’s
data.
As you noticed here , we didn’t need to pass data in the child composable’s parameter.
Let’s take another example
You all used NavHostController
for navigation in jetpack compose. For all the screen NavHostController's
object will be static and same. In that case we can use staticCompositionLocal()
to get rid from passing NavHostController’s
object every time in the composable function’s parameter.
val LocalNavigation = staticCompositionLocalOf<NavHostController> {
error("No object of Navigation")
}
First we created a composition local
of type NavHostController
.
@Composable
fun PerformNavigation() {
val navHostController = LocalNavigation.current
NavHost(navController = navHostController, startDestination = "Screen" ){
composable("screen"){
// your composable
}
}
}
Now with the help of LocalNavigation.current
, get the current value.
CompositionLocalProvider(
LocalNavigation provides rememberNavController(),
) {
PerformNavigation()
}
At last and most important to pass PerformNavigation()
function under CompositionLocalProvider
and also provide rememberNavController()
as a current value.
Now the same NavHostController
object will be used in all the composables .
compositionLocalOf()
In case of compositionLocalOf()
, value will not be static.
The value created with compositionLocalOf()
is mutable and can be modified within the same composition. You can use the current
property of the CompositionLocal
to read and update the value.
Use compositionLocalOf()
when you know value might be change frequently over and over time.
val LocalTextStyleDemo = compositionLocalOf {
// provided default value
CustomTextStyle(
fontSize = 30.sp,
fontWeight = FontWeight.W500,
color = Color.Blue
)
}
Understanding When to Use CompositionLocal
- You need to provide a good default value, or as you learned, throw an error if you forget to provide a default value.
- You can provide a value through
CompositionLocal
when the value is a UI tree-wide value. As you saw before withnavHostController
, you implemented in the previous sections can be used by all composables, a subset, and even several composables at once.
That’s all for today my friends , Hope you enjoyed and learnt something new.