# Decompose GenericComponentContext Architecture: Core Abstraction and Extensions

> Explore GenericComponentContext architecture in Decompose. Learn how it unifies lifecycle, state, and back handling for hierarchical child contexts. Optimize your app structure today.

- Repository: [Arkadii Ivanov/decompose](https://github.com/arkivanov/decompose)
- Tags: architecture
- Published: 2026-02-25

---

**GenericComponentContext is the unified interface in Decompose that aggregates lifecycle, state preservation, instance retention, and back handling capabilities while providing a factory for creating hierarchical child contexts.**

The `GenericComponentContext` interface forms the architectural foundation of the [Decompose](https://github.com/arkivanov/decompose) navigation library by Arkadii Ivanov. This generic abstraction unifies four essential Essenty owner interfaces and enables the recursive creation of component contexts, making it possible to build complex navigation hierarchies with scoped state management.

## The GenericComponentContext Interface

At the center of Decompose's architecture lies the `GenericComponentContext<T>` interface defined in [`decompose/src/commonMain/kotlin/com/arkivanov/decompose/GenericComponentContext.kt`](https://github.com/arkivanov/decompose/blob/main/decompose/src/commonMain/kotlin/com/arkivanov/decompose/GenericComponentContext.kt). This interface extends five critical contracts that provide the full lifecycle and state management toolkit for any component:

```kotlin
interface GenericComponentContext<out T : Any> :
    LifecycleOwner,
    StateKeeperOwner,
    InstanceKeeperOwner,
    BackHandlerOwner,
    ComponentContextFactoryOwner<T>

```

By aggregating these **Essenty** owners, `GenericComponentContext` enables components to react to lifecycle events, persist UI state across process death, retain long-living objects, and handle back-press navigation. The generic type parameter `T` allows the interface to remain covariant while supporting recursive context creation through the factory pattern.

## Factory Pattern and Context Creation

The ability to spawn new contexts without manual dependency wiring comes from two supporting interfaces. First, `ComponentContextFactoryOwner<T>` (located in [`decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextFactoryOwner.kt`](https://github.com/arkivanov/decompose/blob/main/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextFactoryOwner.kt)) exposes the factory:

```kotlin
val componentContextFactory: ComponentContextFactory<T>

```

Second, `ComponentContextFactory<T>` (in [`decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextFactory.kt`](https://github.com/arkivanov/decompose/blob/main/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextFactory.kt)) defines the construction contract as a functional interface:

```kotlin
fun interface ComponentContextFactory<out T : Any> {
    operator fun invoke(
        lifecycle: Lifecycle,
        stateKeeper: StateKeeper,
        instanceKeeper: InstanceKeeper,
        backHandler: BackHandler,
    ): T
}

```

Navigation models like `childStack` leverage this factory to instantiate fresh, detached contexts programmatically. The `operator fun invoke` allows syntactically clean usage: `parentContext.componentContextFactory(...)`.

## DefaultComponentContext Implementation

The concrete implementation `DefaultComponentContext` (in [`decompose/src/commonMain/kotlin/com/arkivanov/decompose/DefaultComponentContext.kt`](https://github.com/arkivanov/decompose/blob/main/decompose/src/commonMain/kotlin/com/arkivanov/decompose/DefaultComponentContext.kt)) wires together the default Essenty dispatchers:

```kotlin
class DefaultComponentContext(
    override val lifecycle: Lifecycle,
    stateKeeper: StateKeeper? = null,
    instanceKeeper: InstanceKeeper? = null,
    backHandler: BackHandler? = null,
) : ComponentContext

```

This class automatically provides `StateKeeperDispatcher`, `InstanceKeeperDispatcher` (attached to the lifecycle), and `BackDispatcher` when null values are passed. The factory implementation simply references the constructor: `ComponentContextFactory(::DefaultComponentContext)`, enabling recursive creation of identical context types.

## Hierarchical Child Contexts

The `childContext` extension function in [`decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextExt.kt`](https://github.com/arkivanov/decompose/blob/main/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextExt.kt) enables the creation of scoped child contexts that maintain proper lifecycle boundaries:

```kotlin
fun <Ctx : GenericComponentContext<Ctx>> Ctx.childContext(
    key: String,
    lifecycle: Lifecycle? = null,
    backHandlerPriority: Int = 0,
): Ctx

```

This function performs three critical operations:
- **Merges lifecycles** using `MergedLifecycle` when a child lifecycle is provided, or inherits the parent lifecycle when null
- **Forks state and instance keepers** via `child(key, lifecycle)` calls on the parent's keepers, creating isolated scopes
- **Creates prioritized back handlers** allowing children to intercept navigation events before parents

The resulting context is constructed through the parent's `componentContextFactory`, ensuring type consistency across the hierarchy.

## Jetpack Integration Architecture

For Android-specific requirements, `JetpackComponentContext` (in [`jetpack-component-context/src/commonMain/kotlin/com/arkivanov/decompose/jetpackcomponentcontext/JetpackComponentContext.kt`](https://github.com/arkivanov/decompose/blob/main/jetpack-component-context/src/commonMain/kotlin/com/arkivanov/decompose/jetpackcomponentcontext/JetpackComponentContext.kt)) extends the generic architecture:

```kotlin
interface JetpackComponentContext :
    GenericComponentContext<JetpackComponentContext>,
    androidx.lifecycle.LifecycleOwner,
    SavedStateRegistryOwner,
    ViewModelStoreOwner,
    HasDefaultViewModelProviderFactory

```

This interface bridges Decompose's generic lifecycle with Android Jetpack's `Lifecycle`, `SavedStateRegistry`, and `ViewModelStore`. The conversion helper enables interoperability:

```kotlin
fun <T : GenericComponentContext<T>> T.asJetpackComponentContext(): JetpackComponentContext

```

The implementation uses a nested `Lifecycle` class that satisfies both Essenty's `Lifecycle` and Jetpack's `LifecycleOwner` contracts simultaneously, allowing a single object to serve both ecosystems.

## Practical Usage Examples

### Creating a Root Context

```kotlin
import com.arkivanov.decompose.DefaultComponentContext
import com.arkivanov.essenty.lifecycle.LifecycleRegistry

val rootLifecycle = LifecycleRegistry().apply {
    create()
    start()
    resume()
}
val rootContext = DefaultComponentContext(lifecycle = rootLifecycle)

```

### Spawning a Child with Scoped State

```kotlin
import com.arkivanov.decompose.childContext

val childContext = rootContext.childContext(
    key = "featureA",
    lifecycle = null,  // Inherits parent lifecycle
    backHandlerPriority = 1  // Handles back before siblings
)

```

### Converting for Android ViewModel Usage

```kotlin
// In an Android-specific module
val jetpackContext = rootContext.asJetpackComponentContext()
val viewModel = jetpackContext.viewModel<MyViewModel>()

```

### Implementing a Custom Context Type

```kotlin
interface AnalyticsContext : 
    GenericComponentContext<AnalyticsContext>,
    AnalyticsProvider {

    class Impl(
        override val lifecycle: Lifecycle,
        override val stateKeeper: StateKeeper,
        override val instanceKeeper: InstanceKeeper,
        override val backHandler: BackHandler,
    ) : AnalyticsContext {
        override val componentContextFactory = 
            ComponentContextFactory(::Impl)
        override val analytics: Analytics = AnalyticsImpl()
    }
}

```

## Summary

- **GenericComponentContext** aggregates `LifecycleOwner`, `StateKeeperOwner`, `InstanceKeeperOwner`, `BackHandlerOwner`, and `ComponentContextFactoryOwner` into a single generic contract.
- **Factory interfaces** enable navigation models to create detached contexts without manual Essenty object construction.
- **DefaultComponentContext** provides the standard concrete implementation wiring Essenty dispatchers together.
- **childContext** extensions create hierarchical scopes with merged lifecycles, forked keepers, and prioritized back handling.
- **JetpackComponentContext** extends the generic architecture to support Android-specific lifecycle, saved state, and ViewModel requirements.

## Frequently Asked Questions

### What is the difference between GenericComponentContext and ComponentContext?

`ComponentContext` is a type alias for `GenericComponentContext<ComponentContext>`, serving as the default concrete type used by most Decompose components. `GenericComponentContext<T>` is the generic base interface that supports custom context types while maintaining the core Essenty owner contracts and factory capabilities.

### How does childContext maintain proper scoping?

The `childContext` extension in [`ComponentContextExt.kt`](https://github.com/arkivanov/decompose/blob/main/ComponentContextExt.kt) creates isolated scopes by calling `stateKeeper.child(key)` and `instanceKeeper.child(key, lifecycle)`, which return forked keepers tied to the child's lifecycle. This ensures state and instances are properly garbage collected when the child lifecycle is destroyed, preventing memory leaks in deeply nested navigation stacks.

### Can I use GenericComponentContext with Android Jetpack ViewModels?

Yes. By calling `asJetpackComponentContext()` on any `GenericComponentContext`, you receive a `JetpackComponentContext` that implements `ViewModelStoreOwner` and `HasDefaultViewModelProviderFactory`. This allows direct usage of `by viewModels()` or `by activityViewModels()` delegates within Decompose components while maintaining the library's multiplatform architecture.

### What is the purpose of the ComponentContextFactory functional interface?

`ComponentContextFactory` abstracts the construction logic for creating new contexts, allowing navigation machinery to instantiate child contexts without knowing the specific implementation class. The factory receives raw Essenty primitives (`Lifecycle`, `StateKeeper`, etc.) and returns a properly configured context of type `T`, enabling type-safe hierarchical composition across custom context implementations.