我有一个带有一些可变状态列表的组件。我将其中的一个项目以及删除该项目的回调传递给另一个组件。
@Composable
fun MyApp() {
val myItems = mutableStateListOf("1", "2", "3")
LazyColumn {
items(myItems) { item ->
MyComponent(item) { toDel -> myItems.remove(toDel) }
}
}
}
组件在修饰符中调用delete
回调。clickable
@Composable
fun MyComponent(item: String, delete: (String) -> Unit = {}) {
Column {
Box(
Modifier
.size(200.dp)
.background(MaterialTheme.colors.primary)
.clickable { delete(item) }
) {
Text(item, fontSize = 40.sp)
}
}
}
这工作正常。但是当我clickable
为我自己的修改器更改时,pointerInput()
就会出现问题。
fun Modifier.myClickable(delete: () -> Unit) =
pointerInput(Unit) {
awaitPointerEventScope { awaitFirstDown() }
delete()
}
@Composable
fun MyComponent(item: String, delete: (String) -> Unit = {}) {
Column {
Box(
Modifier
.size(200.dp)
.background(MaterialTheme.colors.primary)
.myClickable { delete(item) } // NEW
) {
Text(item, fontSize = 40.sp)
}
}
}
如果我单击第一项,它将删除它。接下来,如果我单击最新的顶部项目,则会调用现在已删除的第一项的旧回调,尽管旧组件已被删除。
我不知道为什么会这样。但我可以修复它。我使用key()
:
@Composable
fun MyApp() {
val myItems = mutableStateListOf("1", "2", "3")
LazyColumn {
items(myItems) { item ->
key(item) { // NEW
MyComponent(item) { toDel -> myItems.remove(toDel) }
}
}
}
}
key()
那么,当我使用自己的修饰符时,为什么需要?jetpack的这段代码也是这种情况,我不知道为什么。
正如接受的答案所说,Compose 不会重新计算我的自定义修饰符,因为pointerEvent()
没有唯一键。
fun Modifier.myClickable(key:Any? = null, delete: () -> Unit) =
pointerInput(key) {
awaitPointerEventScope { awaitFirstDown() }
delete()
}
和
Box(
Modifier
.size(200.dp)
.background(MaterialTheme.colors.primary)
.myClickable(key = item) { delete(item) } // NEW
) {
Text(item, fontSize = 40.sp)
}
修复它,我不需要key()
在外部组件中使用。但是,我仍然不确定为什么我不需要向 发送唯一密钥clickable {}
。