【发布时间】:2021-08-15 16:44:46
【问题描述】:
我有一个带有一些可变状态列表的组件。我将其中的一个项目以及删除该项目的回调传递给另一个组件。
@Composable
fun MyApp() {
val myItems = mutableStateListOf("1", "2", "3")
LazyColumn {
items(myItems) { item ->
MyComponent(item) { toDel -> myItems.remove(toDel) }
}
}
}
组件在 clickable 修饰符中调用 delete 回调。
@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)
}
}
}
这很好用。但是当我用pointerInput() 为我自己的修饰符更改clickable 时,就会出现问题。
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 {} 发送唯一密钥。
【问题讨论】:
标签: android android-jetpack-compose android-jetpack-compose-list