Fixed movableContent composite hash key to be consistent
The value of `currentCompositeKeyHash` is now consistent between restarts
of the applciation and activity lifecyle changes.
Fixes: b/222584631
Test: ./gradlew :compose:r:r:tDUT
Change-Id: I289dccb028217f410814285d55b4b58b3c6afaa5
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
index 23350c7..d415c3b 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
@@ -2669,7 +2669,7 @@
// All movable content has a compound hash value rooted at the content itself so the hash
// value doesn't change as the content moves in the tree.
val savedCompoundKeyHash = compoundKeyHash
- compoundKeyHash = movableContentKey xor content.hashCode()
+ compoundKeyHash = movableContentKey
// Either insert a place-holder to be inserted later (either created new or moved from
// another location) or (re)compose the movable content. This is forced if a new value
diff --git a/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/MovableContentTests.kt b/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/MovableContentTests.kt
index 84d5124..00c5a0e 100644
--- a/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/MovableContentTests.kt
+++ b/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/MovableContentTests.kt
@@ -29,6 +29,7 @@
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
+import kotlin.test.assertNotEquals
import kotlin.test.assertSame
import kotlin.test.assertTrue
@@ -1252,6 +1253,37 @@
expectChanges()
revalidate()
}
+
+ @Test
+ fun movableContentOfTheSameFunctionShouldHaveStableKeys() = compositionTest {
+ val hashList1 = mutableListOf<Int>()
+ val hashList2 = mutableListOf<Int>()
+ val composable1: @Composable () -> Unit = {
+ hashList1.add(currentCompositeKeyHash)
+ }
+ val composable2: @Composable () -> Unit = {
+ hashList2.add(currentCompositeKeyHash)
+ }
+ val movableContent1A = movableContentOf(composable1)
+ val movableContent1B = movableContentOf(composable1)
+ val movableContent2A = movableContentOf(composable2)
+ val movableContent2B = movableContentOf(composable2)
+ compose {
+ movableContent1A()
+ movableContent1B()
+ movableContent1A()
+ movableContent1B()
+ movableContent2A()
+ movableContent2B()
+ movableContent2A()
+ movableContent2B()
+ }
+
+ fun List<Int>.assertAllTheSame() = forEach { assertEquals(it, first()) }
+ hashList1.assertAllTheSame()
+ hashList2.assertAllTheSame()
+ assertNotEquals(hashList1.first(), hashList2.first())
+ }
}
@Composable