diff --git a/decompose/api/android/decompose.api b/decompose/api/android/decompose.api
index 1a0d3e6a1..54a9c63a3 100644
--- a/decompose/api/android/decompose.api
+++ b/decompose/api/android/decompose.api
@@ -70,10 +70,10 @@ public abstract interface annotation class com/arkivanov/decompose/InternalDecom
 }
 
 public final class com/arkivanov/decompose/RetainedComponentKt {
-	public static final fun retainedComponent (Landroidx/activity/ComponentActivity;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Ljava/lang/Object;
-	public static final fun retainedComponent (Landroidx/fragment/app/Fragment;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Ljava/lang/Object;
-	public static synthetic fun retainedComponent$default (Landroidx/activity/ComponentActivity;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object;
-	public static synthetic fun retainedComponent$default (Landroidx/fragment/app/Fragment;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object;
+	public static final fun retainedComponent (Landroidx/activity/ComponentActivity;Ljava/lang/String;ZZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+	public static final fun retainedComponent (Landroidx/fragment/app/Fragment;Ljava/lang/String;ZZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+	public static synthetic fun retainedComponent$default (Landroidx/activity/ComponentActivity;Ljava/lang/String;ZZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object;
+	public static synthetic fun retainedComponent$default (Landroidx/fragment/app/Fragment;Ljava/lang/String;ZZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object;
 }
 
 public final class com/arkivanov/decompose/UtilsKt {
diff --git a/decompose/src/androidMain/kotlin/com/arkivanov/decompose/RetainedComponent.kt b/decompose/src/androidMain/kotlin/com/arkivanov/decompose/RetainedComponent.kt
index 139b3ecad..017029b8d 100644
--- a/decompose/src/androidMain/kotlin/com/arkivanov/decompose/RetainedComponent.kt
+++ b/decompose/src/androidMain/kotlin/com/arkivanov/decompose/RetainedComponent.kt
@@ -25,6 +25,7 @@ import com.arkivanov.essenty.lifecycle.subscribe
 import com.arkivanov.essenty.statekeeper.SerializableContainer
 import com.arkivanov.essenty.statekeeper.StateKeeperDispatcher
 import com.arkivanov.essenty.statekeeper.stateKeeper
+import kotlinx.serialization.builtins.serializer
 
 /**
  * Returns (creating if needed) a component that is retained over configuration changes.
@@ -34,17 +35,26 @@ import com.arkivanov.essenty.statekeeper.stateKeeper
  *
  * @param key a key of the component, must be unique within the `Activity`.
  * @param handleBackButton a flag that determines whether back button handling is enabled or not, default is `true`.
+ * @param discardSavedState a flag indicating whether any previously saved state should be discarded or not,
+ * default value is `false`. Can be useful for handling deep links in `onCreate`, so that the navigation state
+ * is not restored and initial state from the deep link is applied instead.
+ * @param isStateSavingAllowed called before saving the state. When `true` then the state will be saved,
+ * otherwise it won't. Default value is `true`.
  * @param factory a function that returns a new instance of the component.
  */
 @ExperimentalDecomposeApi
 fun <T> ComponentActivity.retainedComponent(
     key: String = "RootRetainedComponent",
     handleBackButton: Boolean = true,
+    discardSavedState: Boolean = false,
+    isStateSavingAllowed: () -> Boolean = { true },
     factory: (ComponentContext) -> T,
 ): T =
     retainedComponent(
         key = key,
         onBackPressedDispatcher = if (handleBackButton) onBackPressedDispatcher else null,
+        discardSavedState = discardSavedState,
+        isStateSavingAllowed = isStateSavingAllowed,
         isChangingConfigurations = ::isChangingConfigurations,
         factory = factory,
     )
@@ -57,30 +67,43 @@ fun <T> ComponentActivity.retainedComponent(
  *
  * @param key a key of the component, must be unique within the `Fragment`.
  * @param handleBackButton a flag that determines whether back button handling is enabled or not, default is `true`.
+ * @param discardSavedState a flag indicating whether any previously saved state should be discarded or not,
+ * default value is `false`. Can be useful for handling deep links in `onCreate`, so that the navigation state
+ * is not restored and initial state from the deep link is applied instead.
+ * @param isStateSavingAllowed called before saving the state. When `true` then the state will be saved,
+ * otherwise it won't. Default value is `true`.
  * @param factory a function that returns a new instance of the component.
  */
 @ExperimentalDecomposeApi
 fun <T> Fragment.retainedComponent(
     key: String = "RootRetainedComponent",
     handleBackButton: Boolean = true,
+    discardSavedState: Boolean = false,
+    isStateSavingAllowed: () -> Boolean = { true },
     factory: (ComponentContext) -> T,
 ): T =
     retainedComponent(
         key = key,
         onBackPressedDispatcher = if (handleBackButton) requireActivity().onBackPressedDispatcher else null,
+        discardSavedState = discardSavedState,
+        isStateSavingAllowed = isStateSavingAllowed,
         isChangingConfigurations = { activity?.isChangingConfigurations ?: false },
         factory = factory,
     )
 
-private fun <T, O> O.retainedComponent(
+internal fun <T, O> O.retainedComponent(
     key: String,
     onBackPressedDispatcher: OnBackPressedDispatcher?,
+    discardSavedState: Boolean,
+    isStateSavingAllowed: () -> Boolean,
     isChangingConfigurations: () -> Boolean,
     factory: (ComponentContext) -> T,
 ): T where O : LifecycleOwner, O : SavedStateRegistryOwner, O : ViewModelStoreOwner {
     val lifecycle = essentyLifecycle()
-    val stateKeeper = stateKeeper()
-    val instanceKeeper = instanceKeeper()
+    val stateKeeper = stateKeeper(discardSavedState = discardSavedState, isSavingAllowed = isStateSavingAllowed)
+    val marker = stateKeeper.consume(key = KEY_STATE_MARKER, strategy = String.serializer())
+    stateKeeper.register(key = KEY_STATE_MARKER, strategy = String.serializer()) { "marker" }
+    val instanceKeeper = instanceKeeper(discardRetainedInstances = marker == null)
 
     check(!stateKeeper.isRegistered(key = key)) { "Another retained component is already registered with the key: $key" }
 
@@ -124,6 +147,8 @@ private fun <T, O> O.retainedComponent(
     return holder.component
 }
 
+private const val KEY_STATE_MARKER = "RetainedComponent_state_marker"
+
 private class DelegateOnBackPressedCallback(
     private val dispatcher: OnBackPressedDispatcher,
 ) : OnBackPressedCallback(enabled = dispatcher.hasEnabledCallbacks()) {
diff --git a/decompose/src/androidUnitTest/kotlin/com/arkivanov/decompose/AndroidTestUtils.kt b/decompose/src/androidUnitTest/kotlin/com/arkivanov/decompose/AndroidTestUtils.kt
new file mode 100644
index 000000000..5c7069e36
--- /dev/null
+++ b/decompose/src/androidUnitTest/kotlin/com/arkivanov/decompose/AndroidTestUtils.kt
@@ -0,0 +1,16 @@
+package com.arkivanov.decompose
+
+import com.arkivanov.essenty.lifecycle.Lifecycle
+import com.arkivanov.essenty.lifecycle.subscribe
+
+fun Lifecycle.logEvents(): MutableList<String> =
+    ArrayList<String>().apply {
+        subscribe(
+            onCreate = { add("onCreate") },
+            onStart = { add("onStart") },
+            onResume = { add("onResume") },
+            onPause = { add("onPause") },
+            onStop = { add("onStop") },
+            onDestroy = { add("onDestroy") },
+        )
+    }
diff --git a/decompose/src/androidUnitTest/kotlin/com/arkivanov/decompose/DefaultComponentContextBuilderTest.kt b/decompose/src/androidUnitTest/kotlin/com/arkivanov/decompose/DefaultComponentContextBuilderTest.kt
index ae33f473c..117415bab 100644
--- a/decompose/src/androidUnitTest/kotlin/com/arkivanov/decompose/DefaultComponentContextBuilderTest.kt
+++ b/decompose/src/androidUnitTest/kotlin/com/arkivanov/decompose/DefaultComponentContextBuilderTest.kt
@@ -1,23 +1,12 @@
 package com.arkivanov.decompose
 
-import android.os.Bundle
-import android.os.Parcel
-import androidx.activity.OnBackPressedDispatcher
-import androidx.activity.OnBackPressedDispatcherOwner
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LifecycleOwner
-import androidx.lifecycle.LifecycleRegistry
-import androidx.lifecycle.ViewModelStore
-import androidx.lifecycle.ViewModelStoreOwner
-import androidx.savedstate.SavedStateRegistry
-import androidx.savedstate.SavedStateRegistryController
-import androidx.savedstate.SavedStateRegistryOwner
 import com.arkivanov.decompose.router.TestInstance
 import com.arkivanov.essenty.backhandler.BackCallback
 import com.arkivanov.essenty.instancekeeper.getOrCreate
 import org.junit.runner.RunWith
 import org.robolectric.RobolectricTestRunner
 import kotlin.test.Test
+import kotlin.test.assertContentEquals
 import kotlin.test.assertEquals
 import kotlin.test.assertFalse
 import kotlin.test.assertNotSame
@@ -30,12 +19,59 @@ import kotlin.test.assertTrue
 class DefaultComponentContextBuilderTest {
 
     @Test
-    fun saves_and_restores_state() {
+    fun WHEN_created_THEN_lifecycle_resumed() {
+        val owner = TestOwner()
+        val ctx = owner.defaultComponentContext()
+        val events = ctx.lifecycle.logEvents()
+
+        assertContentEquals(listOf("onCreate", "onStart", "onResume"), events)
+    }
+
+    @Test
+    fun WHEN_recreated_THEN_old_lifecycle_destroyed() {
+        var owner = TestOwner()
+        val ctx = owner.defaultComponentContext()
+        val events = ctx.lifecycle.logEvents()
+        events.clear()
+
+        owner = owner.recreate(isChangingConfigurations = false)
+        owner.defaultComponentContext()
+
+        assertContentEquals(listOf("onPause", "onStop", "onDestroy"), events)
+    }
+
+    @Test
+    fun WHEN_recreated_THEN_new_lifecycle_resumed() {
+        var owner = TestOwner()
+        owner.defaultComponentContext()
+
+        owner = owner.recreate(isChangingConfigurations = false)
+        val ctx = owner.defaultComponentContext()
+        val events = ctx.lifecycle.logEvents()
+
+        assertContentEquals(listOf("onCreate", "onStart", "onResume"), events)
+    }
+
+    @Test
+    fun WHEN_recreated_THEN_saves_and_restores_state() {
         var owner = TestOwner()
         var ctx = owner.defaultComponentContext()
         ctx.stateKeeper.register(key = "key") { "saved_state" }
 
-        owner = owner.recreate()
+        owner = owner.recreate(isChangingConfigurations = false)
+        ctx = owner.defaultComponentContext()
+        val restoredState = ctx.stateKeeper.consume<String>(key = "key")
+
+        assertEquals("saved_state", restoredState)
+    }
+
+    @Test
+    fun WHEN_configuration_changed_THEN_saves_and_restores_state() {
+        var owner = TestOwner()
+        var ctx = owner.defaultComponentContext()
+        ctx.stateKeeper.register(key = "key") { "saved_state" }
+
+        owner = owner.recreate(isChangingConfigurations = true)
         ctx = owner.defaultComponentContext()
         val restoredState = ctx.stateKeeper.consume<String>(key = "key")
 
@@ -56,7 +92,7 @@ class DefaultComponentContextBuilderTest {
     }
 
     @Test
-    fun GIVEN_isStateSavingAllowed_is_false_on_save_THEN_state_not_saved() {
+    fun GIVEN_isStateSavingAllowed_is_false_on_save_WHEN_configuration_changed_THEN_state_not_saved() {
         var owner = TestOwner()
         var ctx = owner.defaultComponentContext(isStateSavingAllowed = { false })
         ctx.stateKeeper.register(key = "key") { "saved_state" }
@@ -69,7 +105,7 @@ class DefaultComponentContextBuilderTest {
     }
 
     @Test
-    fun GIVEN_isStateSavingAllowed_is_false_on_save_THEN_instances_not_retained() {
+    fun GIVEN_isStateSavingAllowed_is_false_on_save_WHEN_configuration_changed_THEN_instances_not_retained() {
         var owner = TestOwner()
         var ctx = owner.defaultComponentContext(isStateSavingAllowed = { false })
         val instance1 = ctx.instanceKeeper.getOrCreate(key = "key", factory = ::TestInstance)
@@ -82,9 +118,9 @@ class DefaultComponentContextBuilderTest {
     }
 
     @Test
-    fun GIVEN_isStateSavingAllowed_is_false_on_save_THEN_old_instances_destroyed() {
+    fun GIVEN_isStateSavingAllowed_is_false_on_save_WHEN_configuration_changed_THEN_old_instances_destroyed() {
         var owner = TestOwner()
-        var ctx = owner.defaultComponentContext(isStateSavingAllowed = { false })
+        val ctx = owner.defaultComponentContext(isStateSavingAllowed = { false })
         val instance1 = ctx.instanceKeeper.getOrCreate(key = "key", factory = ::TestInstance)
 
         owner = owner.recreate()
@@ -94,7 +130,7 @@ class DefaultComponentContextBuilderTest {
     }
 
     @Test
-    fun GIVEN_discardSavedState_is_true_on_restore_THEN_discards_saved_state() {
+    fun WHEN_configuration_changed_and_discardSavedState_is_true_on_restore_THEN_discards_saved_state() {
         var owner = TestOwner()
         var ctx = owner.defaultComponentContext()
         ctx.stateKeeper.register(key = "key") { "saved_state" }
@@ -107,7 +143,7 @@ class DefaultComponentContextBuilderTest {
     }
 
     @Test
-    fun GIVEN_discardSavedState_is_true_on_restore_THEN_instances_not_retained() {
+    fun WHEN_configuration_changed_and_discardSavedState_is_true_on_restore_THEN_instances_not_retained() {
         var owner = TestOwner()
         var ctx = owner.defaultComponentContext()
         val instance1 = ctx.instanceKeeper.getOrCreate(key = "key", factory = ::TestInstance)
@@ -120,7 +156,7 @@ class DefaultComponentContextBuilderTest {
     }
 
     @Test
-    fun GIVEN_discardSavedState_is_true_on_restore_THEN_old_instances_destroyed() {
+    fun WHEN_configuration_changed_and_discardSavedState_is_true_on_restore_THEN_old_instances_destroyed() {
         var owner = TestOwner()
         val ctx = owner.defaultComponentContext()
         val instance1 = ctx.instanceKeeper.getOrCreate(key = "key", factory = ::TestInstance)
@@ -154,39 +190,4 @@ class DefaultComponentContextBuilderTest {
 
         assertFalse(isCalled)
     }
-
-    private class TestOwner(
-        savedState: Bundle = Bundle(),
-        override val viewModelStore: ViewModelStore = ViewModelStore(),
-    ) : LifecycleOwner, SavedStateRegistryOwner, ViewModelStoreOwner, OnBackPressedDispatcherOwner {
-        private val savedStateRegistryController: SavedStateRegistryController = SavedStateRegistryController.create(this)
-        override val lifecycle: Lifecycle = LifecycleRegistry(this)
-        override val savedStateRegistry: SavedStateRegistry get() = savedStateRegistryController.savedStateRegistry
-        override val onBackPressedDispatcher: OnBackPressedDispatcher = OnBackPressedDispatcher()
-
-        init {
-            savedStateRegistryController.performRestore(savedState)
-        }
-
-        fun recreate(): TestOwner {
-            val bundle = Bundle()
-            savedStateRegistryController.performSave(bundle)
-
-            return TestOwner(savedState = bundle.parcelize().deparcelize(), viewModelStore = viewModelStore)
-        }
-
-        private fun Bundle.parcelize(): ByteArray {
-            val parcel = Parcel.obtain()
-            parcel.writeBundle(this)
-            return parcel.marshall()
-        }
-
-        private fun ByteArray.deparcelize(): Bundle {
-            val parcel = Parcel.obtain()
-            parcel.unmarshall(this, 0, size)
-            parcel.setDataPosition(0)
-
-            return requireNotNull(parcel.readBundle())
-        }
-    }
 }
diff --git a/decompose/src/androidUnitTest/kotlin/com/arkivanov/decompose/RetainedComponentTest.kt b/decompose/src/androidUnitTest/kotlin/com/arkivanov/decompose/RetainedComponentTest.kt
new file mode 100644
index 000000000..7ea834162
--- /dev/null
+++ b/decompose/src/androidUnitTest/kotlin/com/arkivanov/decompose/RetainedComponentTest.kt
@@ -0,0 +1,205 @@
+package com.arkivanov.decompose
+
+import com.arkivanov.decompose.router.TestInstance
+import com.arkivanov.essenty.backhandler.BackCallback
+import com.arkivanov.essenty.instancekeeper.getOrCreate
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import kotlin.test.Test
+import kotlin.test.assertContentEquals
+import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+import kotlin.test.assertNotSame
+import kotlin.test.assertNull
+import kotlin.test.assertSame
+import kotlin.test.assertTrue
+
+@Suppress("TestFunctionName")
+@RunWith(RobolectricTestRunner::class)
+class RetainedComponentTest {
+
+    @Test
+    fun WHEN_created_THEN_lifecycle_resumed() {
+        val owner = TestOwner()
+        val ctx = owner.retainedComponent()
+        val events = ctx.lifecycle.logEvents()
+
+        assertContentEquals(listOf("onCreate", "onStart", "onResume"), events)
+    }
+
+    @Test
+    fun WHEN_recreated_THEN_old_lifecycle_destroyed() {
+        var owner = TestOwner()
+        val ctx = owner.retainedComponent()
+        val events = ctx.lifecycle.logEvents()
+        events.clear()
+
+        owner = owner.recreate(isChangingConfigurations = false)
+        owner.retainedComponent()
+
+        assertContentEquals(listOf("onPause", "onStop", "onDestroy"), events)
+    }
+
+    @Test
+    fun WHEN_recreated_THEN_new_lifecycle_resumed() {
+        var owner = TestOwner()
+        owner.retainedComponent()
+
+        owner = owner.recreate(isChangingConfigurations = false)
+        val ctx = owner.retainedComponent()
+        val events = ctx.lifecycle.logEvents()
+
+        assertContentEquals(listOf("onCreate", "onStart", "onResume"), events)
+    }
+
+    @Test
+    fun WHEN_configuration_changed_THEN_lifecycle_not_called() {
+        var owner = TestOwner()
+        val ctx = owner.retainedComponent(isChangingConfigurations = { true })
+        val events = ctx.lifecycle.logEvents()
+        events.clear()
+
+        owner = owner.recreate(isChangingConfigurations = true)
+        owner.retainedComponent()
+
+        assertContentEquals(emptyList(), events)
+    }
+
+    @Test
+    fun WHEN_recreated_THEN_saves_and_restores_state() {
+        var owner = TestOwner()
+        var ctx = owner.retainedComponent()
+        ctx.stateKeeper.register(key = "key") { "saved_state" }
+
+        owner = owner.recreate(isChangingConfigurations = false)
+        ctx = owner.retainedComponent()
+        val restoredState = ctx.stateKeeper.consume<String>(key = "key")
+
+        assertEquals("saved_state", restoredState)
+    }
+
+    @Test
+    fun retains_instances() {
+        var owner = TestOwner()
+        val ctx1 = owner.retainedComponent()
+
+        owner = owner.recreate()
+        val ctx2 = owner.retainedComponent()
+
+        assertSame(ctx1, ctx2)
+    }
+
+    @Test
+    fun GIVEN_isStateSavingAllowed_is_false_on_save_WHEN_recreated_THEN_state_not_saved() {
+        var owner = TestOwner()
+        var ctx = owner.retainedComponent(isStateSavingAllowed = { false })
+        ctx.stateKeeper.register(key = "key") { "saved_state" }
+
+        owner = owner.recreate(isChangingConfigurations = false)
+        ctx = owner.retainedComponent()
+        val restoredState = ctx.stateKeeper.consume<String>(key = "key")
+
+        assertNull(restoredState)
+    }
+
+    @Test
+    fun GIVEN_isStateSavingAllowed_is_false_on_save_WHEN_configuration_changed_THEN_instances_not_retained() {
+        var owner = TestOwner()
+        var ctx = owner.retainedComponent(isStateSavingAllowed = { false })
+        val instance1 = ctx.instanceKeeper.getOrCreate(key = "key", factory = ::TestInstance)
+
+        owner = owner.recreate(isChangingConfigurations = true)
+        ctx = owner.retainedComponent()
+        val instance2 = ctx.instanceKeeper.getOrCreate(key = "key", factory = ::TestInstance)
+
+        assertNotSame(instance1, instance2)
+    }
+
+    @Test
+    fun GIVEN_isStateSavingAllowed_is_false_on_save_WHEN_configuration_changed_THEN_old_instances_destroyed() {
+        var owner = TestOwner()
+        val ctx = owner.retainedComponent(isStateSavingAllowed = { false })
+        val instance1 = ctx.instanceKeeper.getOrCreate(key = "key", factory = ::TestInstance)
+
+        owner = owner.recreate(isChangingConfigurations = true)
+        owner.retainedComponent()
+
+        assertTrue(instance1.isDestroyed)
+    }
+
+    @Test
+    fun WHEN_configuration_changed_and_discardSavedState_is_true_on_restore_THEN_discards_saved_state() {
+        var owner = TestOwner()
+        var ctx = owner.retainedComponent()
+        ctx.stateKeeper.register(key = "key") { "saved_state" }
+
+        owner = owner.recreate(isChangingConfigurations = true)
+        ctx = owner.retainedComponent(discardSavedState = true)
+        val restoredState = ctx.stateKeeper.consume<String>(key = "key")
+
+        assertNull(restoredState)
+    }
+
+    @Test
+    fun WHEN_configuration_changed_and_discardSavedState_is_true_on_restore_THEN_instances_not_retained() {
+        var owner = TestOwner()
+        var ctx = owner.retainedComponent()
+        val instance1 = ctx.instanceKeeper.getOrCreate(key = "key", factory = ::TestInstance)
+
+        owner = owner.recreate(isChangingConfigurations = true)
+        ctx = owner.retainedComponent(discardSavedState = true)
+        val instance2 = ctx.instanceKeeper.getOrCreate(key = "key", factory = ::TestInstance)
+
+        assertNotSame(instance1, instance2)
+    }
+
+    @Test
+    fun WHEN_configuration_changed_and_discardSavedState_is_true_on_restore_THEN_old_instances_destroyed() {
+        var owner = TestOwner()
+        val ctx = owner.retainedComponent()
+        val instance1 = ctx.instanceKeeper.getOrCreate(key = "key", factory = ::TestInstance)
+
+        owner = owner.recreate(isChangingConfigurations = true)
+        owner.retainedComponent(discardSavedState = true)
+
+        assertTrue(instance1.isDestroyed)
+    }
+
+    @Test
+    fun GIVEN_enabled_BackCallback_registered_WHEN_onBackPressed_THEN_callback_called() {
+        val owner = TestOwner()
+        val ctx = owner.retainedComponent()
+        var isCalled = false
+        ctx.backHandler.register(BackCallback { isCalled = true })
+
+        owner.onBackPressedDispatcher.onBackPressed()
+
+        assertTrue(isCalled)
+    }
+
+    @Test
+    fun GIVEN_disabled_BackCallback_registered_WHEN_onBackPressed_THEN_callback_not_called() {
+        val owner = TestOwner()
+        val ctx = owner.defaultComponentContext()
+        var isCalled = false
+        ctx.backHandler.register(BackCallback(isEnabled = false) { isCalled = true })
+
+        owner.onBackPressedDispatcher.onBackPressed()
+
+        assertFalse(isCalled)
+    }
+
+    private fun TestOwner.retainedComponent(
+        discardSavedState: Boolean = false,
+        isStateSavingAllowed: () -> Boolean = { true },
+        isChangingConfigurations: () -> Boolean = { false },
+    ): ComponentContext =
+        retainedComponent(
+            key = "key",
+            onBackPressedDispatcher = onBackPressedDispatcher,
+            discardSavedState = discardSavedState,
+            isStateSavingAllowed = isStateSavingAllowed,
+            isChangingConfigurations = isChangingConfigurations,
+            factory = { it },
+        )
+}
diff --git a/decompose/src/androidUnitTest/kotlin/com/arkivanov/decompose/TestOwner.kt b/decompose/src/androidUnitTest/kotlin/com/arkivanov/decompose/TestOwner.kt
new file mode 100644
index 000000000..2673ed347
--- /dev/null
+++ b/decompose/src/androidUnitTest/kotlin/com/arkivanov/decompose/TestOwner.kt
@@ -0,0 +1,57 @@
+package com.arkivanov.decompose
+
+import android.os.Bundle
+import android.os.Parcel
+import androidx.activity.OnBackPressedDispatcher
+import androidx.activity.OnBackPressedDispatcherOwner
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.LifecycleRegistry
+import androidx.lifecycle.ViewModelStore
+import androidx.lifecycle.ViewModelStoreOwner
+import androidx.savedstate.SavedStateRegistry
+import androidx.savedstate.SavedStateRegistryController
+import androidx.savedstate.SavedStateRegistryOwner
+
+class TestOwner(
+    savedState: Bundle = Bundle(),
+    override val viewModelStore: ViewModelStore = ViewModelStore(),
+) : LifecycleOwner, SavedStateRegistryOwner, ViewModelStoreOwner, OnBackPressedDispatcherOwner {
+    private val savedStateRegistryController: SavedStateRegistryController = SavedStateRegistryController.create(this)
+    override val lifecycle: LifecycleRegistry = LifecycleRegistry(this)
+    override val savedStateRegistry: SavedStateRegistry get() = savedStateRegistryController.savedStateRegistry
+    override val onBackPressedDispatcher: OnBackPressedDispatcher = OnBackPressedDispatcher()
+
+    init {
+        savedStateRegistryController.performRestore(savedState)
+        lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
+    }
+
+    fun recreate(isChangingConfigurations: Boolean = true): TestOwner {
+        val bundle = Bundle()
+        savedStateRegistryController.performSave(bundle)
+        val savedState = bundle.parcelize().deparcelize()
+        lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
+
+        return if (isChangingConfigurations) {
+            TestOwner(savedState = savedState, viewModelStore = viewModelStore)
+        } else {
+            viewModelStore.clear()
+            TestOwner(savedState = savedState)
+        }
+    }
+
+    private fun Bundle.parcelize(): ByteArray {
+        val parcel = Parcel.obtain()
+        parcel.writeBundle(this)
+        return parcel.marshall()
+    }
+
+    private fun ByteArray.deparcelize(): Bundle {
+        val parcel = Parcel.obtain()
+        parcel.unmarshall(this, 0, size)
+        parcel.setDataPosition(0)
+
+        return requireNotNull(parcel.readBundle())
+    }
+}