Understanding the Relationship Between Child and Child.Created in Decompose

In Decompose, Child.Created is a concrete subclass of the sealed Child class that represents an active navigation instance with a non-null component, while Child serves as the polymorphic base type for both active and destroyed children.

Decompose is a Kotlin Multiplatform library for building component-based architectures with navigation. At the heart of its navigation system lies the Child sealed class hierarchy, which models the lifecycle state of each screen or component in the navigation stack. Understanding the relationship between the base Child type and its Child.Created subclass is essential for working with routers like ChildStack and ChildPages.

The Child Sealed Class Hierarchy

The foundation of Decompose's navigation model is defined in decompose/src/commonMain/kotlin/com/arkivanov/decompose/Child.kt. This file declares Child as a generic sealed class with two type parameters: C for the configuration type and T for the component instance type.

sealed class Child<out C : Any, out T : Any> {
    abstract val configuration: C
    abstract val instance: T?
    abstract val key: String
}

The class exposes three abstract properties:

  • configuration: The immutable configuration object used to create the component
  • instance: The live component instance, which may be null if the child has been destroyed
  • key: A unique string identifier used for state restoration and diffing

Child.Created vs Child.Destroyed

The Child sealed class has two concrete implementations that represent distinct lifecycle states. This design allows Decompose to maintain type safety while handling both active and inactive navigation entries.

Child.Created - The Active Instance

Child.Created represents a child that is currently instantiated and active. It is the primary type you will encounter when working with visible screens in your navigation stack.

Key characteristics:

  • The instance property is guaranteed to be non-null
  • It appears in router outputs like ChildStack.active and ChildPages.items
  • It carries the full component lifecycle

Child.Destroyed - The Inactive State

Child.Destroyed represents a child that has been removed from the active navigation state but whose configuration is retained. This is useful for back-stack persistence and state restoration scenarios.

Key characteristics:

  • The instance property is always null
  • It maintains the configuration and key for potential recreation
  • It appears in historical navigation records

Working with Child.Created in Practice

When building UIs with Decompose, you will typically interact with Child.Created instances obtained from routers. The sealed class structure enables exhaustive when-expressions for type-safe handling.

Pattern matching on Child types:

when (val child = someChild) {
    is Child.Created -> {
        // child.instance is guaranteed non-null
        render(child.instance)
    }
    is Child.Destroyed -> {
        // Handle destroyed state or placeholder
    }
}

Accessing the active child from ChildStack:

import com.arkivanov.decompose.router.stack.ChildStack

val stack: ChildStack<String, MyScreenComponent> = routerState()
val topChild: Child.Created<String, MyScreenComponent> = stack.active
val screen = topChild.instance  // Non-null, safe to use

Filtering created children from a collection:

val configs = children
    .filterIsInstance<Child.Created<*, *>>()
    .map { it.configuration }

Key Implementation Files

The following source files define and utilize the Child hierarchy in the Decompose library:

File Role
decompose/src/commonMain/kotlin/com/arkivanov/decompose/Child.kt Defines the sealed Child class and its Created and Destroyed subclasses.
decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/stack/ChildStack.kt Exposes navigation state as a stack of Child objects; the active property returns Child.Created.
decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/pages/ChildPages.kt Implements pager-style navigation using Child.Created for visible pages.
extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/Children.kt Provides Compose integration that renders children via a @Composable (Child.Created<C, T>) -> Unit lambda.

Summary

  • Child is a sealed base class that represents any navigation entry in Decompose, whether active or destroyed.
  • Child.Created is a concrete subclass that guarantees a non-null component instance and represents an active screen in the navigation stack.
  • Child.Destroyed represents inactive entries with null instances, useful for back-stack persistence.
  • The sealed hierarchy enables type-safe pattern matching and polymorphic handling in routers like ChildStack and ChildPages.
  • Source files Child.kt, ChildStack.kt, and ChildPages.kt implement this architecture.

Frequently Asked Questions

Is Child.Created always returned by routers in Decompose?

Yes, active router outputs like ChildStack.active and visible items in ChildPages always return Child.Created instances, which guarantees that the component instance is available for rendering. Historical or destroyed entries may be represented as Child.Destroyed when maintaining back-stack state.

Can I create Child.Created instances manually?

While the framework typically creates Child.Created instances internally through routers, you can instantiate them directly using the constructor if needed for testing or custom navigation implementations. The constructor accepts the configuration, instance, and key parameters as defined in the sealed class hierarchy.

Why does Child.instance return a nullable type if Child.Created guarantees a non-null instance?

The base Child class defines instance as nullable (T?) to accommodate Child.Destroyed, where the instance is always null. When you have a Child.Created reference, smart casting in Kotlin automatically narrows the type to non-null, allowing safe access without additional null checks.

How does Decompose use Child.Destroyed in navigation state restoration?

Child.Destroyed maintains the configuration and unique key of a removed child without holding the component instance, allowing Decompose to persist navigation history efficiently. When restoring state, the framework can recreate the component from the stored configuration if the user navigates back to that destination.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →