androidx.navigation3.runtime


Interfaces

NavKey

Marker interface for keys.

Cmn

Classes

EntryClassProvider

Holds a Entry class, metadata, and content for that class

Cmn
EntryProvider

Holds a Entry class, metadata, and content for that key

Cmn
EntryProviderBuilder

DSL for constructing a new NavEntry

Cmn
NavEntry

Entry maintains and stores the key and the content represented by that key.

Cmn
NavEntryDecorator

Marker class to hold the onPop and decorator functions that will be invoked at runtime.

Cmn
NavEntryWrapper

Class that wraps a NavEntry within another NavEntry.

Cmn

Annotations

EntryDsl
Cmn

Type aliases

NavBackStack

A List of objects that extend the NavKey marker class.

android

Top-level functions summary

Unit
@Composable
<T : Any> DecorateNavEntry(
    entry: NavEntry<T>,
    entryDecorators: List<NavEntryDecorator<*>>
)

Wraps a NavEntry with the list of NavEntryDecorator in the order that the decorators were added to the list and invokes the content of the wrapped entry.

Cmn
Unit
@Composable
<T : Any> DecoratedNavEntryProvider(
    backStack: List<T>,
    entryProvider: (key) -> NavEntry<T>,
    entryDecorators: List<NavEntryDecorator<*>>,
    content: @Composable (List<NavEntry<T>>) -> Unit
)

Function that provides all of the NavEntrys wrapped with the given NavEntryDecorators.

Cmn
inline <Error class: unknown class><SnapshotStateList<T>>

Creates a KSerializer for a SnapshotStateList of T representing a back stack.

Cmn
android
NavEntryDecorator<Any>

Wraps the content of a NavEntry with a SaveableStateHolder.SaveableStateProvider to ensure that calls to rememberSaveable within the content work properly and that state can be saved.

Cmn
inline (T) -> NavEntry<T>
<T : Any> entryProvider(
    noinline fallback: (unknownScreen) -> NavEntry<T>,
    builder: EntryProviderBuilder<T>.() -> Unit
)

Creates an EntryProviderBuilder with the entry providers provided in the builder.

Cmn
NavEntryDecorator<T>
<T : Any> navEntryDecorator(
    onPop: (contentKey: Any) -> Unit,
    decorator: @Composable (entry: NavEntry<T>) -> Unit
)

Function to decorate the NavEntry that are integrated with a DecoratedNavEntryProvider.

Cmn
inline SnapshotStateList<NavKey>
@Composable
<T : NavKey> rememberNavBackStack(
    vararg elements: T,
    configuration: SavedStateConfiguration
)

Provides a NavBackStack that is automatically remembered in the Compose hierarchy across process death and configuration changes.

android
NavEntryDecorator<Any>

Returns a SavedStateNavEntryDecorator that is remembered across recompositions.

Cmn

Extension functions summary

inline Unit
<T : Any> EntryProviderBuilder<*>.entry(
    noinline clazzContentKey: (key) -> Any,
    metadata: Map<StringAny>,
    noinline content: @Composable (T) -> Unit
)

Add an entry provider to the EntryProviderBuilder

Cmn
Unit
<T : Any> EntryProviderBuilder<T>.entry(
    key: T,
    contentKey: Any,
    metadata: Map<StringAny>,
    content: @Composable (T) -> Unit
)

Add an entry provider to the EntryProviderBuilder

Cmn

Top-level functions

DecorateNavEntry

@Composable
fun <T : Any> DecorateNavEntry(
    entry: NavEntry<T>,
    entryDecorators: List<NavEntryDecorator<*>>
): Unit

Wraps a NavEntry with the list of NavEntryDecorator in the order that the decorators were added to the list and invokes the content of the wrapped entry.

Parameters
<T : Any>

the type of the backStack key

entry: NavEntry<T>

the NavEntry to wrap

entryDecorators: List<NavEntryDecorator<*>>

the list of decorators to wrap the entry with

DecoratedNavEntryProvider

@Composable
fun <T : Any> DecoratedNavEntryProvider(
    backStack: List<T>,
    entryProvider: (key) -> NavEntry<T>,
    entryDecorators: List<NavEntryDecorator<*>> = listOf(rememberSavedStateNavEntryDecorator()),
    content: @Composable (List<NavEntry<T>>) -> Unit
): Unit

Function that provides all of the NavEntrys wrapped with the given NavEntryDecorators. It is responsible for executing the functions provided by each NavEntryDecorator appropriately.

Note: the order in which the NavEntryDecorators are added to the list determines their scope, i.e. a NavEntryDecorator added earlier in a list has its data available to those added later.

Parameters
<T : Any>

the type of the backStack key

backStack: List<T>

the list of keys that represent the backstack

entryProvider: (key) -> NavEntry<T>

a function that returns the NavEntry for a given key

entryDecorators: List<NavEntryDecorator<*>> = listOf(rememberSavedStateNavEntryDecorator())

the NavEntryDecorators that are providing data to the content

content: @Composable (List<NavEntry<T>>) -> Unit

the content to be displayed

inline fun <T : Any> NavBackStackSerializer(
    configuration: SavedStateConfiguration = SavedStateConfiguration.DEFAULT
): <Error class: unknown class><SnapshotStateList<T>>

Creates a KSerializer for a SnapshotStateList of T representing a back stack.

This factory configures element serialization for open or closed polymorphic stacks, returning a serializer suitable for saving/restoring a back stack with kotlinx.serialization.

Use this serializer when wiring a back stack (SnapshotStateList of T) into saved state (e.g., with rememberSerializable or any API that accepts a KSerializer).

Important: If T is polymorphic (e.g., a interface hierarchy), the encoder/decoder must be created with the same SerializersModule you used to obtain the serializer. The module lives on the Encoder/Decoder, not inside the KSerializer instance. That means:

  • When you pass a custom SavedStateConfiguration, you must also pass that configuration (or at least its SerializersModule) to your Encoder/Decoder calls. Otherwise, polymorphic dispatch will fail at runtime with "Serializer for subclass ... is not found".

  • The Android DEFAULT path uses a reflective serializer that is self-contained and does not require a module on the Encoder/Decoder.

Platform behavior:

  • Android:

    • With SavedStateConfiguration.DEFAULT, uses a reflective element serializer that works for any @Serializable subtype of T.

    • With a custom SavedStateConfiguration, resolves the element serializer from the provided serializersModule (supporting open or closed polymorphism as configured).

    • Limitation: reflective lookup does not preserve generic type parameters. For example, List<Foo> and List<Bar> are both treated as List<*>. If you need generic type support, supply an explicit SavedStateConfiguration with a registered SerializersModule.

  • Non-Android:

    • Always resolves the element serializer from the provided SavedStateConfiguration.serializersModule.

    • You must register the hierarchy for T (e.g., polymorphic base + subclasses) in that module and also pass the same module to the Encoder/Decoder.

Closed vs. open polymorphism:

  • Closed hierarchies (sealed classes) have all subtypes known at compile time, so serializers can be generated without a module.

  • Open hierarchies (interfaces, non-sealed classes) require a SerializersModule to register subtypes for polymorphic dispatch.

Example

interface Screen
@Serializable data class Home(val id: String) : Screen
@
Serializable data class Details(val itemId: Long) : Screen

val
module = SerializersModule {
polymorphic(Screen::class) {
subclass(Home::class, Home.serializer())
subclass(Details::class, Details.serializer())
}
}

val configuration = SavedStateConfiguration(serializersModule = module)

val serializer = NavBackStackSerializer<Screen>(configuration)

// Pass the same configuration (or at least its serializersModule) to encode/decode:
val encoded = encodeToSavedState(configuration, serializer, backStack)
val decoded = decodeFromSavedState(configuration, serializer, encoded)
Parameters
<T : Any>

element type stored in the back stack.

configuration: SavedStateConfiguration = SavedStateConfiguration.DEFAULT

controls how element serializers are resolved. On Android, DEFAULT enables reflection; otherwise the provided serializersModule is used.

Returns
<Error class: unknown class><SnapshotStateList<T>>

a KSerializer for a SnapshotStateList of T for a back stack.

SavedStateNavEntryDecorator

fun SavedStateNavEntryDecorator(saveableStateHolder: SaveableStateHolder): NavEntryDecorator<Any>

Wraps the content of a NavEntry with a SaveableStateHolder.SaveableStateProvider to ensure that calls to rememberSaveable within the content work properly and that state can be saved. Also provides the content of a NavEntry with a SavedStateRegistryOwner which can be accessed in the content with LocalSavedStateRegistryOwner.

This NavEntryDecorator is the only one that is required as saving state is considered a non-optional feature.

Parameters
saveableStateHolder: SaveableStateHolder

the SaveableStateHolder that holds the state defined with rememberSaveable. A saved state can only be restored from the SaveableStateHolder that it was saved with.

inline fun <T : Any> entryProvider(
    noinline fallback: (unknownScreen) -> NavEntry<T> = { throw IllegalStateException("Unknown screen $it") },
    builder: EntryProviderBuilder<T>.() -> Unit
): (T) -> NavEntry<T>

Creates an EntryProviderBuilder with the entry providers provided in the builder.

Parameters
<T : Any>

the type of the NavEntry key

noinline fallback: (unknownScreen) -> NavEntry<T> = { throw IllegalStateException("Unknown screen $it") }

the fallback NavEntry when the provider cannot find an entry associated with a given key on the backStack

builder: EntryProviderBuilder<T>.() -> Unit

the EntryProviderBuilder DSL extension that builds NavEntries for the provider

fun <T : Any> navEntryDecorator(
    onPop: (contentKey: Any) -> Unit = {},
    decorator: @Composable (entry: NavEntry<T>) -> Unit
): NavEntryDecorator<T>

Function to decorate the NavEntry that are integrated with a DecoratedNavEntryProvider.

Primary usages include but are not limited to:

  1. provide information to entries with androidx.compose.runtime.CompositionLocal, i.e.

val decorator = navEntryDecorator<Any> { entry ->
...
CompositionLocalProvider(LocalMyStateProvider provides myState) {
entry.content.invoke(entry.key)
}
}
  1. Wrap entry content with other composable content

val decorator = navEntryDecorator<Any> { entry ->
...
MyComposableFunction {
entry.content.invoke(entry.key)
}
}
Parameters
<T : Any>

the type of the backStack key

onPop: (contentKey: Any) -> Unit = {}

the callback to clean up the decorator state for a NavEntry when the entry is popped from the backstack and is leaving composition.The lambda provides the NavEntry.contentKey of the popped entry as input.

decorator: @Composable (entry: NavEntry<T>) -> Unit

the composable function to decorate a NavEntry. Note that this function only gets invoked for NavEntries that are actually getting rendered (i.e. by invoking the NavEntry.content.)

rememberNavBackStack

@Composable
inline fun <T : NavKey> rememberNavBackStack(
    vararg elements: T,
    configuration: SavedStateConfiguration = SavedStateConfiguration.DEFAULT
): SnapshotStateList<NavKey>

Provides a NavBackStack that is automatically remembered in the Compose hierarchy across process death and configuration changes.

This function uses NavBackStackSerializer under the hood to save and restore the back stack via rememberSerializable.

Serialization requirements

  • Each element placed in the NavBackStack must be @Serializable.

  • For closed polymorphism (sealed hierarchies), the compiler knows all subtypes and generates serializers automatically. No custom SavedStateConfiguration is required.

  • For open polymorphism (interfaces or non-sealed hierarchies):

    • On Android, SavedStateConfiguration.DEFAULT uses a reflective serializer that can handle subtypes without registration.

    • On other platforms, or when you supply a custom configuration, you must register all subtypes of NavKey in a SerializersModule and pass that via configuration. You must also provide the same configuration to the encoder/decoder when saving/restoring state.

Example

@Serializable sealed interface Screen : NavKey
@
Serializable data class Home(val id: String) : Screen
@
Serializable data class Details(val itemId: Long) : Screen

// Closed polymorphism with sealed interface works out of the box on Android:
val backStack = rememberNavBackStack(Home("sta

rt"))// Open polymorphism requires registering subtypes (non
-Android):val module = Serialize
rsModule { polymorphic(Screen
::class) { subclass(Home::class, Home.ser
ializer()) subclass(Details::class, Details.ser
ial
i
zer()) }}val config = SavedStateConfiguration(serializersModule
= module)val backStack = rememberNavBackStack(Home("start"), configuration = config)
Parameters
vararg elements: T

The initial keys of this back stack.

configuration: SavedStateConfiguration = SavedStateConfiguration.DEFAULT

Controls how element serializers are resolved. On Android, SavedStateConfiguration.DEFAULT uses reflection; otherwise, the provided SerializersModule is used.

Returns
SnapshotStateList<NavKey>

A NavBackStack that survives process death and configuration changes.

rememberSavedStateNavEntryDecorator

@Composable
fun rememberSavedStateNavEntryDecorator(
    saveableStateHolder: SaveableStateHolder = rememberSaveableStateHolder()
): NavEntryDecorator<Any>

Returns a SavedStateNavEntryDecorator that is remembered across recompositions.

Parameters
saveableStateHolder: SaveableStateHolder = rememberSaveableStateHolder()

the SaveableStateHolder that scopes the returned NavEntryDecorator

Extension functions

inline fun <T : Any> EntryProviderBuilder<*>.entry(
    noinline clazzContentKey: (key) -> Any = { defaultContentKey(it) },
    metadata: Map<StringAny> = emptyMap(),
    noinline content: @Composable (T) -> Unit
): Unit

Add an entry provider to the EntryProviderBuilder

Parameters
<T : Any>

the type of the key for this NavEntry

noinline clazzContentKey: (key) -> Any = { defaultContentKey(it) }

A factory of unique, stable ids that uniquely identifies the content of this NavEntry. To maximize stability, it should be derived from the factory's provided key. The resulting key must be saveable (i.e. on Android, it should be saveable via Android). The generated key will be stored in NavEntry.contentKey.

metadata: Map<StringAny> = emptyMap()

provides information to the display

noinline content: @Composable (T) -> Unit

content for this entry to be displayed when this entry is active

fun <T : Any> EntryProviderBuilder<T>.entry(
    key: T,
    contentKey: Any = defaultContentKey(key),
    metadata: Map<StringAny> = emptyMap(),
    content: @Composable (T) -> Unit
): Unit

Add an entry provider to the EntryProviderBuilder

Parameters
<T : Any>

the type of the key for this NavEntry

key: T

key for this entry

contentKey: Any = defaultContentKey(key)

A unique, stable id that uniquely identifies the content of this NavEntry. To maximize stability, it should be derived from the key. The contentKey type must be saveable (i.e. on Android, it should be saveable via Android). Defaults to key.toString().

metadata: Map<StringAny> = emptyMap()

provides information to the display

content: @Composable (T) -> Unit

content for this entry to be displayed when this entry is active