Regenerate semantics id when the layout node is reused.
Bug: 281908278
Change-Id: I6868da7db3aa166ecc4351787a6e3f3b37332d8a
Test: the newly added test case will fail if not regenerate the id.
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/semantics/SemanticsTests.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/semantics/SemanticsTests.kt
index f27b445..d8504fad 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/semantics/SemanticsTests.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/semantics/SemanticsTests.kt
@@ -26,9 +26,12 @@
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ReusableContent
import androidx.compose.runtime.Stable
+import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
@@ -65,6 +68,7 @@
import kotlin.math.max
import org.junit.After
import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
@@ -953,6 +957,25 @@
.assertContentDescriptionEquals("hello world")
.assertTestPropertyEquals("bar")
}
+
+ @Test
+ fun testRegenerateSemanticsId() {
+ var reuseKey by mutableStateOf(0)
+ rule.setContent {
+ ReusableContent(reuseKey) {
+ Box(
+ Modifier.testTag(TestTag)
+ )
+ }
+ }
+ val oldId = rule.onNodeWithTag(TestTag).fetchSemanticsNode().id
+ rule.runOnIdle {
+ reuseKey = 1
+ }
+ val newId = rule.onNodeWithTag(TestTag).fetchSemanticsNode().id
+
+ assertNotEquals(oldId, newId)
+ }
}
private fun SemanticsNodeInteraction.assertDoesNotHaveProperty(property: SemanticsPropertyKey<*>) {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
index aa215e9..574419a 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
@@ -82,7 +82,7 @@
// subcompose multiple times into the same LayoutNode and define offsets.
private val isVirtual: Boolean = false,
// The unique semantics ID that is used by all semantics modifiers attached to this LayoutNode.
- override val semanticsId: Int = generateSemanticsId()
+ override var semanticsId: Int = generateSemanticsId()
) : ComposeNodeLifecycleCallback,
Remeasurement,
OwnerScope,
@@ -1321,6 +1321,7 @@
}
// resetModifierState detaches all nodes, so we need to re-attach them upon reuse.
nodes.attach()
+ semanticsId = generateSemanticsId()
}
override fun onDeactivate() {