Repository: arkivanov/Decompose
Pull request #353 (2023-03-29 18:18:46)

Save state for initially inactive components


Patch:
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildItem.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildItem.kt
index 392cb0c7..d9f67f9d 100644
--- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildItem.kt
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildItem.kt
@@ -10,11 +10,9 @@ internal sealed interface ChildItem<out C : Any, out T : Any> {
 
     val configuration: C
     val instance: T?
-    val savedState: ParcelableContainer?
 
     data class Created<out C : Any, out T : Any>(
         override val configuration: C,
-        override val savedState: ParcelableContainer? = null,
         override val instance: T,
         val lifecycleRegistry: LifecycleRegistry,
         val stateKeeperDispatcher: StateKeeperDispatcher,
@@ -24,7 +22,7 @@ internal sealed interface ChildItem<out C : Any, out T : Any> {
 
     data class Destroyed<out C : Any>(
         override val configuration: C,
-        override val savedState: ParcelableContainer? = null
+        val savedState: ParcelableContainer? = null
     ) : ChildItem<C, Nothing> {
         override val instance: Nothing? = null
     }
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenFactory.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenFactory.kt
index 28e5f4be..9193344e 100644
--- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenFactory.kt
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenFactory.kt
@@ -75,6 +75,8 @@ fun <C : Any, T : Any, E : Any, N : NavState<C>, S : Any> ComponentContext.child
 
     val navigator =
         stateKeeper.consume<SavedState>(key = key).let { savedState ->
+            val restoredNavState: N? = savedState?.navState?.let(restoreState)
+
             ChildrenNavigator(
                 lifecycle = lifecycle,
                 retainedInstanceSupplier = { factory -> instanceKeeper.getOrCreate(key = key, factory = factory) },
@@ -83,8 +85,8 @@ fun <C : Any, T : Any, E : Any, N : NavState<C>, S : Any> ComponentContext.child
                     backHandler = backHandler.child(),
                     childFactory = childFactory,
                 ),
-                navState = savedState?.navState?.let(restoreState) ?: initialState(),
-                savedChildState = savedState?.childState,
+                navState = restoredNavState ?: initialState(),
+                savedChildState = savedState?.childState?.takeUnless { restoredNavState == null },
             )
         }
 
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenNavigator.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenNavigator.kt
index b65e43b4..231d47c0 100644
--- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenNavigator.kt
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenNavigator.kt
@@ -100,7 +100,7 @@ internal class ChildrenNavigator<out C : Any, out T : Any, N : NavState<C>>(
     fun saveChildState(): List<ParcelableContainer?> =
         items.map { item ->
             when (item) {
-                is Created -> item.saveStateIfNeeded()
+                is Created -> item.stateKeeperDispatcher.save()
                 is ChildItem.Destroyed -> item.savedState
             }
         }
@@ -192,13 +192,6 @@ internal class ChildrenNavigator<out C : Any, out T : Any, N : NavState<C>>(
         }
     }
 
-    private fun Created<*, *>.saveStateIfNeeded(): ParcelableContainer? =
-        if (lifecycleRegistry.state > Lifecycle.State.CREATED) {
-            stateKeeperDispatcher.save()
-        } else {
-            savedState
-        }
-
     private fun processNewItems(newItems: List<Pair<ChildItem<C, T>, Status>>) {
         items.clear()
         retainedInstance.items.clear()
@@ -209,7 +202,7 @@ internal class ChildrenNavigator<out C : Any, out T : Any, N : NavState<C>>(
                     is Created -> {
                         when (status) {
                             Status.DESTROYED -> {
-                                val savedState = item.saveStateIfNeeded()
+                                val savedState = item.stateKeeperDispatcher.save()
                                 item.backHandler.stop()
                                 item.instanceKeeperDispatcher.destroy()
                                 item.lifecycleRegistry.destroy()
@@ -222,7 +215,6 @@ internal class ChildrenNavigator<out C : Any, out T : Any, N : NavState<C>>(
 
                                 item
                                     .takeIf { it.lifecycleRegistry.state != Lifecycle.State.CREATED }
-                                    ?.copy(savedState = item.saveStateIfNeeded())
                                     ?.apply {
                                         backHandler.stop()
                                         lifecycleRegistry.stop()
@@ -235,7 +227,6 @@ internal class ChildrenNavigator<out C : Any, out T : Any, N : NavState<C>>(
 
                                 item
                                     .takeIf { it.lifecycleRegistry.state != Lifecycle.State.RESUMED }
-                                    ?.copy(savedState = null)
                                     ?.apply {
                                         backHandler.start()
                                         lifecycleRegistry.resume()


Test patch:
diff --git a/decompose/src/commonTest/kotlin/com/arkivanov/decompose/router/children/ChildrenSavedStateTest.kt b/decompose/src/commonTest/kotlin/com/arkivanov/decompose/router/children/ChildrenSavedStateTest.kt
index b281db7b..1e26018f 100644
--- a/decompose/src/commonTest/kotlin/com/arkivanov/decompose/router/children/ChildrenSavedStateTest.kt
+++ b/decompose/src/commonTest/kotlin/com/arkivanov/decompose/router/children/ChildrenSavedStateTest.kt
@@ -19,7 +19,7 @@ import kotlin.test.assertTrue
 internal class ChildrenSavedStateTest : ChildrenTestBase() {
 
     @Test
-    fun WHEN_child_switched_from_active_to_inactive_THEN_state_saved() {
+    fun WHEN_child_switched_from_active_to_inactive_THEN_state_not_saved() {
         val children by context.children(initialState = stateOf(1 by DESTROYED, 2 by INACTIVE, 3 by ACTIVE))
         var isCalled = false
         children.getById(id = 3).requireInstance().stateKeeper.register(key = "key") {
@@ -29,7 +29,7 @@ internal class ChildrenSavedStateTest : ChildrenTestBase() {
 
         navigate { listOf(1 by DESTROYED, 2 by INACTIVE, 3 by INACTIVE) }
 
-        assertTrue(isCalled)
+        assertFalse(isCalled)
     }
 
     @Test
@@ -47,7 +47,7 @@ internal class ChildrenSavedStateTest : ChildrenTestBase() {
     }
 
     @Test
-    fun WHEN_child_switched_from_inactive_to_destroyed_THEN_state_not_saved() {
+    fun WHEN_child_switched_from_inactive_to_destroyed_THEN_state_saved() {
         val children by context.children(initialState = stateOf(1 by DESTROYED, 2 by INACTIVE, 3 by ACTIVE))
         var isCalled = false
         children.getById(id = 2).requireInstance().stateKeeper.register(key = "key") {
@@ -57,7 +57,7 @@ internal class ChildrenSavedStateTest : ChildrenTestBase() {
 
         navigate { listOf(1 by DESTROYED, 2 by DESTROYED, 3 by ACTIVE) }
 
-        assertFalse(isCalled)
+        assertTrue(isCalled)
     }
 
     @Test
@@ -183,14 +183,17 @@ internal class ChildrenSavedStateTest : ChildrenTestBase() {
         val oldStateKeeper = TestStateKeeperDispatcher()
         val oldContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = oldStateKeeper)
         val oldChildren by oldContext.children(initialState = stateOf(1 by DESTROYED, 2 by INACTIVE, 3 by ACTIVE))
+        oldChildren.getById(id = 2).requireInstance().stateKeeper.register(key = "key") { Config(id = 20) }
         oldChildren.getById(id = 3).requireInstance().stateKeeper.register(key = "key") { Config(id = 30) }
 
         val savedState = oldStateKeeper.save()
         val newStateKeeper = TestStateKeeperDispatcher(savedState)
         val newContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper)
         val newChildren by newContext.children()
+        val restoredState2 = newChildren.getById(id = 2).requireInstance().stateKeeper.consume<Config>(key = "key")
         val restoredState3 = newChildren.getById(id = 3).requireInstance().stateKeeper.consume<Config>(key = "key")
 
+        assertEquals(Config(id = 20), restoredState2)
         assertEquals(Config(id = 30), restoredState3)
     }
 
@@ -198,15 +201,18 @@ internal class ChildrenSavedStateTest : ChildrenTestBase() {
     fun GIVEN_not_saving_state_WHEN_recreated_THEN_child_states_not_restored() {
         val oldStateKeeper = TestStateKeeperDispatcher()
         val oldContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = oldStateKeeper)
-        val oldChildren by oldContext.children(initialState = stateOf(1 by ACTIVE), saveState = { null })
-        oldChildren.getById(id = 1).requireInstance().stateKeeper.register(key = "key") { Config(id = 30) }
+        val oldChildren by oldContext.children(initialState = stateOf(1 by DESTROYED, 2 by INACTIVE, 3 by ACTIVE), saveState = { null })
+        oldChildren.getById(id = 2).requireInstance().stateKeeper.register(key = "key") { Config(id = 20) }
+        oldChildren.getById(id = 3).requireInstance().stateKeeper.register(key = "key") { Config(id = 30) }
 
         val savedState = oldStateKeeper.save()
         val newStateKeeper = TestStateKeeperDispatcher(savedState)
         val newContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper)
-        val newChildren by newContext.children(initialState = stateOf(1 by ACTIVE))
-        val restoredState3 = newChildren.getById(id = 1).requireInstance().stateKeeper.consume<Config>(key = "key")
+        val newChildren by newContext.children(initialState = stateOf(1 by DESTROYED, 2 by INACTIVE, 3 by ACTIVE))
+        val restoredState2 = newChildren.getById(id = 2).requireInstance().stateKeeper.consume<Config>(key = "key")
+        val restoredState3 = newChildren.getById(id = 3).requireInstance().stateKeeper.consume<Config>(key = "key")
 
+        assertNull(restoredState2)
         assertNull(restoredState3)
     }
 
@@ -214,15 +220,18 @@ internal class ChildrenSavedStateTest : ChildrenTestBase() {
     fun GIVEN_not_restoring_state_WHEN_recreated_THEN_child_states_not_restored() {
         val oldStateKeeper = TestStateKeeperDispatcher()
         val oldContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = oldStateKeeper)
-        val oldChildren by oldContext.children(initialState = stateOf(1 by ACTIVE), saveState = { null })
-        oldChildren.getById(id = 1).requireInstance().stateKeeper.register(key = "key") { Config(id = 30) }
+        val oldChildren by oldContext.children(initialState = stateOf(1 by DESTROYED, 2 by INACTIVE, 3 by ACTIVE))
+        oldChildren.getById(id = 2).requireInstance().stateKeeper.register(key = "key") { Config(id = 20) }
+        oldChildren.getById(id = 3).requireInstance().stateKeeper.register(key = "key") { Config(id = 30) }
 
         val savedState = oldStateKeeper.save()
         val newStateKeeper = TestStateKeeperDispatcher(savedState)
         val newContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper)
-        val newChildren by newContext.children(initialState = stateOf(1 by ACTIVE), restoreState = { null })
-        val restoredState3 = newChildren.getById(id = 1).requireInstance().stateKeeper.consume<Config>(key = "key")
+        val newChildren by newContext.children(initialState = stateOf(1 by DESTROYED, 2 by INACTIVE, 3 by ACTIVE), restoreState = { null })
+        val restoredState2 = newChildren.getById(id = 2).requireInstance().stateKeeper.consume<Config>(key = "key")
+        val restoredState3 = newChildren.getById(id = 3).requireInstance().stateKeeper.consume<Config>(key = "key")
 
+        assertNull(restoredState2)
         assertNull(restoredState3)
     }
 
@@ -259,4 +268,28 @@ internal class ChildrenSavedStateTest : ChildrenTestBase() {
 
         assertEquals(Config(id = 30), restoredState3)
     }
+
+    @Test
+    fun GIVEN_child_switched_to_inactive_and_recreated_twice_WHEN_child_switched_to_active_THEN_state_restored() {
+        val oldStateKeeper = TestStateKeeperDispatcher()
+        val oldContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = oldStateKeeper)
+        val oldChildren by oldContext.children(initialState = stateOf(1 by DESTROYED, 2 by ACTIVE, 3 by ACTIVE))
+        oldChildren.getById(id = 2).requireInstance().stateKeeper.register(key = "key") { Config(id = 30) }
+        navigate { listOf(1 by DESTROYED, 2 by INACTIVE, 3 by ACTIVE) }
+
+        val savedState1 = oldStateKeeper.save()
+        val newStateKeeper1 = TestStateKeeperDispatcher(savedState1)
+        val newContext1 = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper1)
+        val newChildren1 by newContext1.children(restoreState = { stateOf(1 by DESTROYED, 2 by INACTIVE, 3 by ACTIVE) })
+        newChildren1.getById(id = 2).requireInstance().stateKeeper.register(key = "key") { Config(id = 31) }
+
+        val savedState2 = newStateKeeper1.save()
+        val newStateKeeper2 = TestStateKeeperDispatcher(savedState2)
+        val newContext2 = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper2)
+        val newChildren2 by newContext2.children(restoreState = { stateOf(1 by DESTROYED, 2 by INACTIVE, 3 by ACTIVE) })
+
+        val restoredState2 = newChildren2.getById(id = 2).requireInstance().stateKeeper.consume<Config>(key = "key")
+
+        assertEquals(Config(id = 31), restoredState2)
+    }
 }
diff --git a/decompose/src/commonTest/kotlin/com/arkivanov/decompose/router/stack/ChildStackIntegrationTest.kt b/decompose/src/commonTest/kotlin/com/arkivanov/decompose/router/stack/ChildStackIntegrationTest.kt
index 46c8cec8..5d9367d2 100644
--- a/decompose/src/commonTest/kotlin/com/arkivanov/decompose/router/stack/ChildStackIntegrationTest.kt
+++ b/decompose/src/commonTest/kotlin/com/arkivanov/decompose/router/stack/ChildStackIntegrationTest.kt
@@ -19,11 +19,10 @@ import com.arkivanov.essenty.parcelable.Parcelize
 import com.arkivanov.essenty.statekeeper.consume
 import kotlin.test.BeforeTest
 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.assertNotEquals
 import kotlin.test.assertTrue
 
 @Suppress("TestFunctionName")
@@ -221,7 +220,7 @@ class ChildStackIntegrationTest {
         val savedState = oldStateKeeper.save()
         val newStateKeeper = TestStateKeeperDispatcher(savedState)
         val newContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper)
-        val newStack by newContext.childStack(initialStack = emptyList())
+        val newStack by newContext.childStack()
 
         newStack.assertStack(1 to 1, 2 to 2)
     }
@@ -241,7 +240,7 @@ class ChildStackIntegrationTest {
     }
 
     @Test
-    fun WHEN_child_pushed_THEN_state_saved_for_previous_child() {
+    fun WHEN_component_pushed_THEN_state_not_saved_for_previous_component() {
         val stack by context.childStack(initialStack = listOf(Config(1)))
         var isCalled = false
         stack.active.instance.stateKeeper.register(key = "key") {
@@ -251,123 +250,139 @@ class ChildStackIntegrationTest {
 
         navigation.push(Config(2))
 
-        assertTrue(isCalled)
+        assertFalse(isCalled)
     }
 
     @Test
-    fun GIVEN_persistent_WHEN_recreated_THEN_state_restored_for_active_child() {
+    fun GIVEN_persistent_WHEN_recreated_THEN_state_restored_for_all_components() {
         val oldStateKeeper = TestStateKeeperDispatcher()
         val oldContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = oldStateKeeper)
-        val oldStack by oldContext.childStack(initialStack = listOf(Config(1)), persistent = true)
-        oldStack.active.instance.stateKeeper.register(key = "key") { Config(10) }
+        val oldStack by oldContext.childStack(initialStack = listOf(Config(1), Config(2), Config(3)), persistent = true)
+        oldStack.items.forEach { (configuration, instance) ->
+            instance.stateKeeper.register(key = "key") { Config(configuration.id) }
+        }
 
         val savedState = oldStateKeeper.save()
         val newStateKeeper = TestStateKeeperDispatcher(savedState)
         val newContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper)
-        val newStack by newContext.childStack(initialStack = emptyList())
-        val restoredState = newStack.active.instance.stateKeeper.consume<Config>(key = "key")
+        val newStack by newContext.childStack()
+        val restoredStates = newStack.items.map { it.instance.stateKeeper.consume<Config>(key = "key") }
 
-        assertEquals(Config(10), restoredState)
+        assertContentEquals(listOf(Config(1), Config(2), Config(3)), restoredStates)
     }
 
     @Test
-    fun GIVEN_not_persistent_WHEN_recreated_THEN_state_not_restored_for_active_child() {
+    fun GIVEN_persistent_WHEN_recreated_twice_THEN_state_restored_for_all_components() {
         val oldStateKeeper = TestStateKeeperDispatcher()
         val oldContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = oldStateKeeper)
-        val oldStack by oldContext.childStack(initialStack = listOf(Config(1)), persistent = false)
-        oldStack.active.instance.stateKeeper.register(key = "key") { Config(10) }
+        val oldStack by oldContext.childStack(initialStack = listOf(Config(1), Config(2), Config(3)), persistent = true)
+        oldStack.items.forEach { (configuration, instance) ->
+            instance.stateKeeper.register(key = "key") { Config(configuration.id) }
+        }
 
-        val savedState = oldStateKeeper.save()
-        val newStateKeeper = TestStateKeeperDispatcher(savedState)
-        val newContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper)
-        val newStack by newContext.childStack(initialStack = listOf(Config(1)))
-        val restoredState = newStack.active.instance.stateKeeper.consume<Config>(key = "key")
+        val savedState1 = oldStateKeeper.save()
+        val newStateKeeper1 = TestStateKeeperDispatcher(savedState1)
+        val newContext1 = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper1)
+        val newStack1 by newContext1.childStack()
+        newStack1.items.forEach { it.instance.stateKeeper.consume<Config>(key = "key") }
+
+        val savedState2 = oldStateKeeper.save()
+        val newStateKeeper2 = TestStateKeeperDispatcher(savedState2)
+        val newContext2 = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper2)
+        val newStack2 by newContext2.childStack()
+        val restoredStates = newStack2.items.map { it.instance.stateKeeper.consume<Config>(key = "key") }
 
-        assertNull(restoredState)
+        assertContentEquals(listOf(Config(1), Config(2), Config(3)), restoredStates)
     }
 
     @Test
-    fun GIVEN_back_stack_not_empty_and_recreated_WHEN_pop_THEN_state_restored_for_previous_child() {
+    fun GIVEN_not_persistent_WHEN_recreated_THEN_state_not_restored_for_any_component() {
         val oldStateKeeper = TestStateKeeperDispatcher()
         val oldContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = oldStateKeeper)
-        val oldStack by oldContext.childStack(initialStack = listOf(Config(1)))
-        oldStack.active.instance.stateKeeper.register(key = "key") { Config(10) }
-        navigation.push(Config(2))
+        val oldStack by oldContext.childStack(initialStack = listOf(Config(1), Config(2), Config(3)), persistent = false)
+        oldStack.items.forEach { (configuration, instance) ->
+            instance.stateKeeper.register(key = "key") { Config(configuration.id) }
+        }
+
         val savedState = oldStateKeeper.save()
         val newStateKeeper = TestStateKeeperDispatcher(savedState)
         val newContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper)
-        val newStack by newContext.childStack(initialStack = emptyList())
-
-        navigation.pop()
-        val restoredState = newStack.active.instance.stateKeeper.consume<Config>(key = "key")
+        val newStack by newContext.childStack(initialStack = listOf(Config(1), Config(2), Config(3)))
+        val restoredStates = newStack.items.map { it.instance.stateKeeper.consume<Config>(key = "key") }
 
-        assertEquals(Config(10), restoredState)
+        assertContentEquals(listOf(null, null, null), restoredStates)
     }
 
     @Test
-    fun GIVEN_persistent_WHEN_recreated_THEN_instance_retained_for_active_component() {
+    fun GIVEN_persistent_WHEN_recreated_THEN_instance_retained_for_all_components() {
         val oldStateKeeper = TestStateKeeperDispatcher()
         val instanceKeeper = InstanceKeeperDispatcher()
         val oldContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = oldStateKeeper, instanceKeeper = instanceKeeper)
-        val oldStack by oldContext.childStack(initialStack = listOf(Config(1)), persistent = true)
-        val oldInstance = oldStack.active.instance.instanceKeeper.getOrCreate(::TestInstance)
+        val oldStack by oldContext.childStack(initialStack = listOf(Config(1), Config(2), Config(3)), persistent = true)
+        val oldInstances = oldStack.items.map { it.instance.instanceKeeper.getOrCreate(::TestInstance) }
 
         val savedState = oldStateKeeper.save()
         val newStateKeeper = TestStateKeeperDispatcher(savedState)
         val newContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper, instanceKeeper = instanceKeeper)
-        val newStack by newContext.childStack(initialStack = emptyList())
-        val retainedInstance = newStack.active.instance.instanceKeeper.getOrCreate(::TestInstance)
+        val newStack by newContext.childStack()
+        val retainedInstances = newStack.items.map { it.instance.instanceKeeper.getOrCreate(::TestInstance) }
 
-        assertSame(oldInstance, retainedInstance)
+        assertContentEquals(oldInstances, retainedInstances)
     }
 
     @Test
-    fun GIVEN_not_persistent_WHEN_recreated_THEN_instance_not_retained_for_active_component() {
+    fun GIVEN_not_persistent_WHEN_recreated_THEN_instance_not_retained_for_any_component() {
         val oldStateKeeper = TestStateKeeperDispatcher()
         val instanceKeeper = InstanceKeeperDispatcher()
         val oldContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = oldStateKeeper, instanceKeeper = instanceKeeper)
-        val oldStack by oldContext.childStack(initialStack = listOf(Config(1)), persistent = false)
-        val oldInstance = oldStack.active.instance.instanceKeeper.getOrCreate(::TestInstance)
+        val oldStack by oldContext.childStack(initialStack = listOf(Config(1), Config(2), Config(3)), persistent = false)
+        val oldInstances = oldStack.items.map { it.instance.instanceKeeper.getOrCreate(::TestInstance) }
 
         val savedState = oldStateKeeper.save()
         val newStateKeeper = TestStateKeeperDispatcher(savedState)
         val newContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper, instanceKeeper = instanceKeeper)
-        val newStack by newContext.childStack(initialStack = listOf(Config(1)))
-        val newInstance = newStack.active.instance.instanceKeeper.getOrCreate(::TestInstance)
+        val newStack by newContext.childStack(initialStack = listOf(Config(1), Config(2), Config(3)))
+        val retainedInstances = newStack.items.map { it.instance.instanceKeeper.getOrCreate(::TestInstance) }
 
-        assertNotSame(oldInstance, newInstance)
+        oldInstances.forEachIndexed { index, instance ->
+            assertNotEquals(instance, retainedInstances[index])
+        }
     }
 
     @Test
-    fun GIVEN_persistent_WHEN_recreated_THEN_instance_not_destroyed_for_active_component() {
+    fun GIVEN_persistent_WHEN_recreated_THEN_instance_not_destroyed_for_any_component() {
         val oldStateKeeper = TestStateKeeperDispatcher()
         val instanceKeeper = InstanceKeeperDispatcher()
         val oldContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = oldStateKeeper, instanceKeeper = instanceKeeper)
-        val stack by oldContext.childStack(initialStack = listOf(Config(1)), persistent = true)
-        val instance = stack.active.instance.instanceKeeper.getOrCreate(::TestInstance)
+        val stack by oldContext.childStack(initialStack = listOf(Config(1), Config(2), Config(3)), persistent = true)
+        val instances = stack.items.map { it.instance.instanceKeeper.getOrCreate(::TestInstance) }
 
         val savedState = oldStateKeeper.save()
         val newStateKeeper = TestStateKeeperDispatcher(savedState)
         val newContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper, instanceKeeper = instanceKeeper)
-        newContext.childStack(initialStack = emptyList())
+        newContext.childStack()
 
-        assertFalse(instance.isDestroyed)
+        instances.forEach {
+            assertFalse(it.isDestroyed)
+        }
     }
 
     @Test
-    fun GIVEN_not_persistent_WHEN_recreated_THEN_instance_destroyed_for_active_component() {
+    fun GIVEN_not_persistent_WHEN_recreated_THEN_instances_destroyed_for_all_component() {
         val oldStateKeeper = TestStateKeeperDispatcher()
         val instanceKeeper = InstanceKeeperDispatcher()
         val oldContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = oldStateKeeper, instanceKeeper = instanceKeeper)
-        val stack by oldContext.childStack(initialStack = listOf(Config(1)), persistent = false)
-        val instance = stack.active.instance.instanceKeeper.getOrCreate(::TestInstance)
+        val stack by oldContext.childStack(initialStack = listOf(Config(1), Config(2), Config(3)), persistent = false)
+        val instances = stack.items.map { it.instance.instanceKeeper.getOrCreate(::TestInstance) }
 
         val savedState = oldStateKeeper.save()
         val newStateKeeper = TestStateKeeperDispatcher(savedState)
         val newContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper, instanceKeeper = instanceKeeper)
-        newContext.childStack(initialStack = listOf(Config(1)))
+        newContext.childStack(initialStack = listOf(Config(1), Config(2), Config(3)))
 
-        assertTrue(instance.isDestroyed)
+        instances.forEach {
+            assertTrue(it.isDestroyed)
+        }
     }
 
     @Test
@@ -392,13 +407,13 @@ class ChildStackIntegrationTest {
         val savedState = oldStateKeeper.save()
         val newStateKeeper = TestStateKeeperDispatcher(savedState)
         val newContext = DefaultComponentContext(lifecycle = lifecycle, stateKeeper = newStateKeeper, instanceKeeper = instanceKeeper)
-        newContext.childStack(initialStack = emptyList())
+        newContext.childStack()
 
         assertFalse(instance.isDestroyed)
     }
 
     private fun ComponentContext.childStack(
-        initialStack: List<Config>,
+        initialStack: List<Config> = emptyList(),
         persistent: Boolean = true,
     ): Value<ChildStack<Config, Component>> =
         childStack(
@@ -412,6 +427,9 @@ class ChildStackIntegrationTest {
     private val ChildStack<Config, Component>.children: List<Pair<Int, Int>>
         get() = items.map { child -> child.configuration.id to child.instance.id }
 
+    private fun ChildStack<Config, Component>.getById(id: Int): Child.Created<Config, Component> =
+        items.first { it.configuration.id == id }
+
     private fun ChildStack<Config, Component>.assertStack(vararg children: Pair<Int, Int>) {
         assertEquals(children.toList(), this.children)
         assertEquals(Lifecycle.State.RESUMED, active.instance.lifecycle.state)