Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save benigumocom/74e40fcf0ccda0d79df81bcb81b668a6 to your computer and use it in GitHub Desktop.

Select an option

Save benigumocom/74e40fcf0ccda0d79df81bcb81b668a6 to your computer and use it in GitHub Desktop.
// ==========================================================
// 【DEFINITION AREA】
// Must be defined at the TOP-LEVEL (Outside of any @Composable)
// ==========================================================
// A. object: A global, immutable box (Constants)
object AppDesignConfig {
val BrandColor = Color(0xFF6200EE) // Fixed brand color
val CornerRadius = 12.dp
}
// B. compositionLocalOf: The "Smart" dynamic pipe.
// When the provided value changes, only the parts using '.current' recompose.
val LocalUserStatus = compositionLocalOf { "Guest" }
// C. staticCompositionLocalOf: The "High-speed" static foundation.
// When the value changes, the entire tree below the Provider is reset/recomposed.
val LocalAppThemeColor = staticCompositionLocalOf { Color.Gray }
// ==========================================================
// 【UI IMPLEMENTATION AREA】
// ==========================================================
@Composable
fun AppMainScreen() {
// State holders for B and C
var userStatus by remember { mutableStateOf("Guest User") }
var themeColor by remember { mutableStateOf(Color(0xFF03DAC5)) }
// Provider Side: This is where we inject the actual values into the Locals
CompositionLocalProvider(
LocalUserStatus provides userStatus,
LocalAppThemeColor provides themeColor
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(24.dp),
verticalArrangement = Arrangement.spacedBy(20.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("State Sharing Comparison", style = MaterialTheme.typography.headlineMedium)
// A: Direct access to object (No Provider or .current needed)
Button(
onClick = { /* Constant value */ },
colors = ButtonDefaults.buttonColors(containerColor = AppDesignConfig.BrandColor)
) {
Text("A: Using Object Constant")
}
// B: Using compositionLocalOf
UserInfoCard()
// C: Using staticCompositionLocalOf
ThemeColorBox()
Spacer(modifier = Modifier.height(20.dp))
HorizontalDivider()
// Operation Panel
Text("Update State:", style = MaterialTheme.typography.titleMedium)
Button(onClick = { userStatus = "Logged in: John Doe" }) {
Text("Update B (User Status)")
}
Button(onClick = { themeColor = Color.Magenta }) {
Text("Update C (Theme Color)")
}
}
}
}
@Composable
fun UserInfoCard() {
// Consuming B: Only this specific function recomposes when userStatus changes
val status = LocalUserStatus.current
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(containerColor = Color.LightGray.copy(alpha = 0.2f))
) {
Box(modifier = Modifier.padding(16.dp)) {
Text("B (compositionLocalOf): $status")
}
}
}
@Composable
fun ThemeColorBox() {
// Consuming C: If themeColor changes, the entire sub-tree is refreshed
val color = LocalAppThemeColor.current
Surface(
color = color,
modifier = Modifier.size(120.dp),
shape = MaterialTheme.shapes.medium,
shadowElevation = 8.dp
) {
Box(contentAlignment = Alignment.Center) {
Text("C (static)", color = Color.White)
}
}
}
@benigumocom
Copy link
Author

object vs compositionLocalOf vs staticCompositionLocalOf: The Ultimate State Sharing Guide
https://android.benigumo.com/20260223/object-vs-compositionlocalof-vs-staticcompositionlocalof/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment