Skip to content

Instantly share code, notes, and snippets.

@StefMa
Last active March 19, 2026 07:51
Show Gist options
  • Select an option

  • Save StefMa/a9d27ab56e19e4ab4bc1a505d4c46a62 to your computer and use it in GitHub Desktop.

Select an option

Save StefMa/a9d27ab56e19e4ab4bc1a505d4c46a62 to your computer and use it in GitHub Desktop.
CompositionLocal in Jetpack Compose
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
MaterialTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
var analyticsProvider by remember { mutableStateOf<Analytics.Provider>(Analytics.Provider.Firebase) }
CompositionLocalProvider(LocalAnalytics provides Analytics(analyticsProvider)) {
Greeting(modifier = Modifier.padding(innerPadding))
}
}
}
}
}
}
@Composable
fun Greeting(modifier: Modifier = Modifier) {
val analytics = LocalAnalytics.current
analytics.trackEvent("Greeting (Re)composed")
Text(
modifier = modifier,
text = "Hello World!"
)
}
data class Analytics(private val provider: Provider) {
sealed interface Provider {
object LogCat : Provider
object Println : Provider
object Firebase : Provider
}
fun trackEvent(eventName: String) {
when (provider) {
Provider.LogCat -> println("Debug: LogCat - Tracking event: $eventName")
Provider.Println -> println("Debug: Println - Tracking event: $eventName")
Provider.Firebase -> println("Debug: Firebase - Tracking event: $eventName")
}
}
}
val LocalAnalytics = compositionLocalOf { Analytics(Analytics.Provider.Println) }
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
MaterialTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
var analyticsProvider by remember { mutableStateOf<Analytics.Provider>(Analytics.Provider.Firebase) }
CompositionLocalProvider(
LocalAnalytics provides Analytics(analyticsProvider, "main")
) {
Column(Modifier.padding(innerPadding)) {
RadioButton(
text = "Println",
selected = analyticsProvider is Analytics.Provider.Println,
onClick = { analyticsProvider = Analytics.Provider.Println }
)
RadioButton(
text = "LogCat",
selected = analyticsProvider is Analytics.Provider.LogCat,
onClick = { analyticsProvider = Analytics.Provider.LogCat }
)
RadioButton(
text = "Firebase",
selected = analyticsProvider is Analytics.Provider.Firebase,
onClick = { analyticsProvider = Analytics.Provider.Firebase }
)
TrackableButton("0. View")
Column {
CompositionLocalProvider(
LocalAnalytics provides
LocalAnalytics.current.wrapWithPrefix("view1")
) {
TrackableButton("1. View")
Column {
CompositionLocalProvider(
LocalAnalytics provides
LocalAnalytics.current.wrapWithPrefix("view2")
) {
TrackableButton("2. View")
Column {
CompositionLocalProvider(
LocalAnalytics provides
LocalAnalytics.current.wrapWithPrefix("view3")
) {
TrackableButton("3. View")
}
}
}
}
}
}
}
}
}
}
}
}
}
@Composable
fun RadioButton(
text: String,
selected: Boolean,
onClick: () -> Unit,
) {
Row {
androidx.compose.material3.RadioButton(
selected = selected,
onClick = onClick
)
Text(
text = text,
modifier = Modifier
.padding(start = 8.dp)
.align(Alignment.CenterVertically)
)
}
}
@Composable
fun TrackableButton(text: String) {
val analytics = LocalAnalytics.current
val context = LocalContext.current
analytics.trackEvent("TrackableButton (Re)composed")
Button(
onClick = {
analytics.trackEvent("buttonClicked")
Toast.makeText(context, "Button at $text clicked", Toast.LENGTH_SHORT).show()
},
content = { Text(text) }
)
}
data class Analytics(private val provider: Provider, private val eventNamePrefix: String) {
sealed interface Provider {
object LogCat : Provider
object Println : Provider
object Firebase : Provider
}
fun trackEvent(eventName: String) {
when (provider) {
Provider.LogCat -> println("Debug: LogCat - Tracking event: ${eventNamePrefix + "_" + eventName}")
Provider.Println -> println("Debug: Println - Tracking event: ${eventNamePrefix + "_" + eventName}")
Provider.Firebase -> println("Debug: Firebase - Tracking event: ${eventNamePrefix + "_" + eventName}")
}
}
fun wrapWithPrefix(appendPrefix: String): Analytics =
copy(eventNamePrefix = eventNamePrefix + "_" + appendPrefix)
}
val LocalAnalytics = compositionLocalOf { Analytics(Analytics.Provider.Println, "null") }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment