diff --git a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt
index 0e509b8cf9..c2d082c712 100644
--- a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt
+++ b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt
@@ -49,7 +49,7 @@ private class State(
private sealed interface ViewState {
object None : ViewState
- class Preloading(
+ data class Preloading(
val onBackPressedDispatcher: OnBackPressedDispatcher,
val uiConfiguration: UiConfiguration,
) : ViewState
@@ -87,6 +87,7 @@ internal class TreehouseAppContent(
dispatchers.checkUi()
val previousState = stateFlow.value
+ if (previousState.viewState == ViewState.Preloading(onBackPressedDispatcher, uiConfiguration)) return // Idempotent.
check(previousState.viewState is ViewState.None)
val nextViewState = ViewState.Preloading(onBackPressedDispatcher, uiConfiguration)
diff --git a/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/TreehouseAppContentTest.kt b/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/TreehouseAppContentTest.kt
index fcc5dd098b..3c6f0e7b0c 100644
--- a/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/TreehouseAppContentTest.kt
+++ b/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/TreehouseAppContentTest.kt
@@ -446,6 +446,23 @@ class TreehouseAppContentTest {
content.unbind()
}
+ @Test
+ fun preload_idempotent() = runTest {
+ val content = treehouseAppContent()
+
+ codeHost.startCodeSession("codeSessionA")
+ eventLog.takeEvent("codeSessionA.start()")
+
+ content.preload(onBackPressedDispatcher, uiConfiguration)
+ eventLog.takeEvent("codeSessionA.app.uis[0].start()")
+
+ content.preload(onBackPressedDispatcher, uiConfiguration)
+ eventLog.assertNoEvents()
+
+ content.unbind()
+ eventLog.takeEvent("codeSessionA.app.uis[0].close()")
+ }
+
@Test
fun bind_idempotent() = runTest {
val content = treehouseAppContent()