androidx.navigation3.runtime


Interfaces

NavKey

Marker interface for keys.

Cmn

Classes

EntryProviderBuilder

DSL for constructing a new NavEntry

Cmn
NavBackStack

A mutable back stack of NavKey elements that integrates with Compose state.

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

Top-level functions summary

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

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 rememberDecoratedNavEntries.

Cmn
List<NavEntry<T>>
@Composable
<T : Any> rememberDecoratedNavEntries(
    entries: List<NavEntry<T>>,
    entryDecorators: List<NavEntryDecorator<T>>
)

Decorates the entries with the entryDecorators and returns the list of decorated NavEntries.

Cmn
List<NavEntry<T>>
@Composable
<T : Any> rememberDecoratedNavEntries(
    backStack: List<T>,
    entryDecorators: List<NavEntryDecorator<T>>,
    entryProvider: (key) -> NavEntry<T>
)

Remembers and returns a list of NavEntry decorated with the list of entryDecorators

Cmn
NavBackStack<NavKey>
@Composable
<T : NavKey> rememberNavBackStack(vararg elements: T)

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

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

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

Cmn
NavEntryDecorator<T>

Returns a SavedStateNavEntryDecorator that is remembered across recompositions.

Cmn

Top-level functions

SavedStateNavEntryDecorator

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

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 rememberDecoratedNavEntries.

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.)

rememberDecoratedNavEntries

@Composable
fun <T : Any> rememberDecoratedNavEntries(
    entries: List<NavEntry<T>>,
    entryDecorators: List<NavEntryDecorator<T>> = listOf()
): List<NavEntry<T>>

Decorates the entries with the entryDecorators and returns the list of decorated NavEntries.

WHEN TO USE This API can be used to decorate undecorated NavEntry as well as entries that have already been decorated with other NavEntryDecorator.

HOW IT WORKS When you redecorate NavEntries with this function, the entryDecorators passed in here will be invoked first, followed by the original decorators that decorated the entries. For example

val originalDecorator = listOf(navEntryDecorator { println("original") })
val originalEntries = rememberDecoratedNavEntries(backStack, originalDecorator, ...)

val newDecorator = listOf(navEntryDecorator { println("additional") })
val newEntries = rememberDecoratedNavEntries(originalEntries, newDecorator)

// println output
additional
original
Parameters
<T : Any>

the type of the backStack key

entries: List<NavEntry<T>>

the list of NavEntry to decorate. If this list is observable, i.e. a androidx.compose.runtime.snapshots.SnapshotStateList, then updates to this list will automatically trigger a re-calculation of the returned list of NavEntry to reflect the new state.

entryDecorators: List<NavEntryDecorator<T>> = listOf()

the NavEntryDecorators that are providing data to the content. If this list is observable (i.e. a androidx.compose.runtime.snapshots.SnapshotStateList), then updates to this list of decorators will automatically trigger a re-calculation of the returned list of NavEntry to reflect the new decorators state.

Returns
List<NavEntry<T>>

a list of decorated NavEntry

rememberDecoratedNavEntries

@Composable
fun <T : Any> rememberDecoratedNavEntries(
    backStack: List<T>,
    entryDecorators: List<NavEntryDecorator<T>> = listOf(),
    entryProvider: (key) -> NavEntry<T>
): List<NavEntry<T>>

Remembers and returns a list of NavEntry decorated with the list of entryDecorators

The returned list of NavEntry survives configuration change and recompositions but does not survive process death. To ensure that the backStack and its states are recovered properly, the backStack and the entryDecorators's states passed into this function should be hoisted and saved across process death.

For example:

// backStack saved during process death
val backStack = rememberNavBackStack()

// the hoisted SaveableStateHolder used by the decorator is saved during process death
val decorators = listOf(rememberSavedStateNavEntryDecorator())

// finally, decorate the entries
val entries = rememberDecoratedNavEntries(backStack, decorators, entryProvider)

HOW TO USE The returned list of entries should be stored and reused for the same backStack. If you want to support multiple backStacks (i.e. each bottom tab with their own backStack), then each backStack should be their own rememberDecoratedNavEntries with new backStack and entryDecorators passed in.

MUTABLE BACKSTACK NAVIGATE/POP The backStack should be a hoisted OBSERVABLE list, and navigates or pops should be applied directly to this backStack. For example:

val backStack = mutableStateListOf(A)
val entries = rememberDecoratedNavEntries(backStack, ...)

// to navigate
backStack.add(B)

// to pop
backStack.removeLastOrNull()

IMMUTABLE BACKSTACK NAVIGATE/POP This composable also supports navigates and pops with immutable backStack. Simply replace the previous backStack with a new one but DO NOT replace the decorator states. Also, DO NOT create a brand new rememberDecoratedNavEntries. For example

val backStack = mutableStateOf(listOf(1, 2))
val entries = rememberDecoratedNavEntries(backStack, ...)

// to navigate
backStack.value = listOf(1, 2, 3)

// to pop
backStack.value = listOf(1)

MULTIPLE BACKSTACKS Each call to rememberDecoratedNavEntries represents a single backStack. To support multiple backStack, there should be one rememberDecoratedNavEntries for each backStack. For example

val homeBackStack = mutableStateListOf(HomeKey)
val homeDecorators = mutableStateListOf(rememberSavedStateNavEntryDecorator(), ...)
val homeTabEntries = rememberDecoratedNavEntries(homeBackStack, homeDecorators, ...)

val favoritesBackStack = mutableStateListOf(FavoritesKey)
val favoritesDecorators = mutableStateListOf(rememberSavedStateNavEntryDecorator(),...)
val favoritesTabEntries = rememberDecoratedNavEntries(favoritesBackStack, favoritesDecorators, ...)

You can also concatenate multiple backStacks to form a larger one. So, given the above setup:

val concatenatedEntries = homeTabEntries + favoritesTabEntries

// To navigate within the favorites backStack
favoritesBackStack.add(FavoritesDetailKey)

In this case, the updated favoritesBackStack and updated states will be reflected in concatenatedEntries.

Parameters
<T : Any>

the type of the backStack key

backStack: List<T>

the list of keys that represent the backstack. If this backStack is observable, i.e. a androidx.compose.runtime.snapshots.SnapshotStateList, then updates to this backStack will automatically trigger a re-calculation of the list of NavEntry to reflect the new backStack state.

entryDecorators: List<NavEntryDecorator<T>> = listOf()

the NavEntryDecorators that are providing data to the content. If this list is observable (i.e. a androidx.compose.runtime.snapshots.SnapshotStateList), then updates to this list of decorators will automatically trigger a re-calculation of the list of NavEntry to reflect the new decorators state.

entryProvider: (key) -> NavEntry<T>

a function that returns the NavEntry for a given key

Returns
List<NavEntry<T>>

a list of decorated NavEntry

rememberNavBackStack

@Composable
fun <T : NavKey> rememberNavBackStack(vararg elements: T): NavBackStack<NavKey>

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

This overload does not take a SavedStateConfiguration. It relies on the platform default: on Android, state is saved/restored using a reflection-based serializer; on other platforms this will fail at runtime. If you target non-Android platforms, use the overload that accepts a SavedStateConfiguration and register your serializers explicitly.

When to use this overload

  • You are on Android only and want a simple API that uses reflection under the hood.

  • Your back stack elements use closed polymorphism (sealed hierarchies) or otherwise work with Android’s reflective serializer.

Serialization requirements

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

  • For closed polymorphism (sealed hierarchies), the compiler knows all subtypes and generates serializers; Android’s reflection will also work.

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

    • On Android, the reflection path can handle subtypes without manual registration.

    • On non-Android, this overload is unsupported; use the configuration overload and register all subtypes of NavKey in a SerializersModule.

import androidx.navigation3.runtime.rememberNavBackStack
import androidx.navigation3.runtime.samples.RememberNavBackStackSamples.Details
import androidx.navigation3.runtime.samples.RememberNavBackStackSamples.Home

// Works on Android (uses reflection internally).
rememberNavBackStack(Home("start"), Details(42))
Parameters
vararg elements: T

The initial keys of this back stack.

Returns
NavBackStack<NavKey>

A NavBackStack that survives process death and configuration changes on Android.

rememberNavBackStack

@Composable
inline fun <T : NavKey> rememberNavBackStack(
    configuration: SavedStateConfiguration,
    vararg elements: T
): NavBackStack<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.

import androidx.navigation3.runtime.rememberNavBackStack
import androidx.navigation3.runtime.samples.RememberNavBackStackSamples.Details
import androidx.navigation3.runtime.samples.RememberNavBackStackSamples.Home
import androidx.navigation3.runtime.samples.RememberNavBackStackSamples.Screen
import androidx.savedstate.serialization.SavedStateConfiguration

val config = SavedStateConfiguration {
    // Register subtypes for open polymorphism or multiplatform use.
    serializersModule = SerializersModule {
        polymorphic(baseClass = Screen::class) {
            subclass(serializer = Home.serializer())
            subclass(serializer = Details.serializer())
        }
    }
}

// Pass the configuration so encoding/decoding works consistently.
rememberNavBackStack<Screen>(config, Home("start"))
Parameters
configuration: SavedStateConfiguration

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

vararg elements: T

The initial keys of this back stack.

Returns
NavBackStack<NavKey>

A NavBackStack that survives process death and configuration changes.

rememberSavedStateNavEntryDecorator

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

Returns a SavedStateNavEntryDecorator that is remembered across recompositions.

Parameters
saveableStateHolder: SaveableStateHolder = rememberSaveableStateHolder()

the SaveableStateHolder that scopes the returned NavEntryDecorator