我有一个带有一些可变状态列表的组件。我将其中的一个项目和删除该项目的回调传递给另一个组件。
@Composable
fun MyApp() {
val myItems = mutableStateListOf("1", "2", "3")
LazyColumn {
items(myItems) { item ->
MyComponent(item) { toDel -> myItems.remove(toDel) }
}
}
}
组件调用Modifier 中的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
我自己的 Modifier 时,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 {}
。
Compose 试图通过使用键本地化作用域来缓存尽可能多的工作:当它们自上次运行以来没有发生变化时 - 我们使用缓存值,否则我们需要重新计算它。
通过设置key
惰性项,您为remember
内部所有计算定义了一个范围,并且许多系统功能都是使用实现的,remember
因此它发生了很大变化。项目索引是惰性项目中的默认键
因此,在您删除 first 之后item
,第一个惰性项将在与之前相同的上下文中重用
现在我们来到您的myClickable
. 你Unit
作为一个key
进入pointerInput
(它也有一个remember
内部)。通过这样做,您对 recomposer 说:永远不要重新计算这个值,直到上下文发生变化。并且第一个惰性项的上下文没有改变,例如key
仍然是相同的索引,这就是为什么带有删除的 lambdaitem
仍然缓存在该函数中的原因
当您指定惰性项key
等于 时item
,您也在更改所有惰性项的上下文,因此pointerInput
会重新计算。如果你通过你的item
而不是Unit
你会有同样的效果
因此,key
当您需要使用时,您需要使用您的计算不会以糟糕的方式缓存在惰性项之间
在文档中查看有关惰性列键的更多信息
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句