Skip to content

State preservation

Sometimes it might be necessary to preserve state or data in a component when it gets destroyed. A very common use case is Android Activity recreation due to configuration changes, or process death on Android or iOS. The ComponentContext interface extends the StateKeeperOwner interface, which provides the StateKeeper - a multiplatform abstraction for state preservation. It is provided by Essenty library (from the same author).

The decompose module adds Essenty's state-keeper module as api dependency, so you don't need to explicitly add it to your project. Please familiarise yourself with Essenty library, especially with the StateKeeper.

Usage example

import com.arkivanov.decompose.ComponentContext
import com.arkivanov.essenty.parcelable.Parcelable
import com.arkivanov.essenty.parcelable.Parcelize
import com.arkivanov.essenty.statekeeper.consume

class SomeComponent(
    componentContext: ComponentContext
) : ComponentContext by componentContext {

    private var state: State = stateKeeper.consume(key = "SAVED_STATE") ?: State()

    init {
        stateKeeper.register(key = "SAVED_STATE") { state }

    private class State(val someValue: Int = 0) : Parcelable

Darwin (Apple) targets support

Decompose provides an experimental support of state preservation for all Darwin (Apple) targets. It works via Essenty library and parcelize-darwin compiler plugin (from the same author). Please read the documentation of both before using state preservation on Darwin targets.

This only affects your project if you explicitly enable the parcelize-darwin compiler plugin in your project. Otherwise, it's just no-op.

Please refer to the sample iOS app where you can find an example of preserving the state.

JVM/desktop support

Decompose also provides an experimental support of state preservation for JVM/desktop. Similarly to other targets, it works via Essenty library. Currently, there is no Parcelize compiler plugin, Parcelable interface just extends

Due to KT-40218, deserialized object classes are not equal to their original instances. This prevents the navigation state from being restored correctly when a configuration is an object. This will be fixed with the introduction of data object in Kotlin 1.9 (see KT-4107). A workaround for now is to add a readResolve method to every object configuration (see an example).

Please refer to the sample JVM/desktop app where you can find an example of preserving the state.