Skip to content

Compositionlocal and context propagation

CompositionLocal and Context Propagation Deep Dive

Overview

CompositionLocal provides implicit dependency propagation through the compose tree. It is powerful for environment-like values and risky for hidden business dependencies.

Core Concepts

  • providers set values for subtree
  • consumers read local values without explicit params
  • great for theme/system ambient data

Runtime Internals

Reads of locals are tracked like other composition inputs. Provider changes invalidate consumers in affected subtree.

Composition / Recomposition Flow

  • local provided at parent
  • descendants read local
  • provider value changes
  • dependent descendants recompose

State Management

Use locals for cross-cutting environment values, not for feature business state ownership.

Code Examples

val LocalSpacing = compositionLocalOf { 8.dp }

@Composable
fun AppTheme(content: @Composable () -> Unit) {
    CompositionLocalProvider(LocalSpacing provides 12.dp) {
        content()
    }
}

Common Interview Questions

  • Q: When should you avoid CompositionLocal? A: Answer from runtime mechanics: state ownership, recomposition triggers, effect lifecycle, and frame-time impact measured with tooling.
  • Q: How does it differ from dependency injection? A: Frame it around graph ownership: prefer constructor injection, align scopes to lifecycle boundaries, keep contracts explicit, and validate with test replacements.

Production Considerations

  • document every custom local clearly
  • keep number of custom locals manageable
  • provide test replacements for deterministic UI tests

Performance Insights

Broad provider updates can invalidate large subtrees; scope providers as tightly as practical.

Senior-Level Insights

Senior-level guidance: use CompositionLocal as environment plumbing, not as an escape hatch for architectural shortcuts.