new*_*our 2 android android-jetpack-compose android-jetpack-compose-list
我有一个带有一些可变状态列表的组件。我将其中的一个项目以及删除该项目的回调传递给另一个组件。
@Composable
fun MyApp() {
val myItems = mutableStateListOf("1", "2", "3")
LazyColumn {
items(myItems) { item ->
MyComponent(item) { toDel -> myItems.remove(toDel) }
}
}
}
Run Code Online (Sandbox Code Playgroud)
该组件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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
这很好用。但是当我更改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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我点击第一个项目,它就会将其删除。接下来,如果我单击最新的顶部项目,则会调用现在删除的第一项的旧回调,尽管旧组件已被删除。
我不知道为什么会发生这种情况。但我可以解决它。我用key():
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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
key()那么当我使用自己的修饰符时为什么需要呢?jetpack的这段代码也是这种情况,我不知道为什么。
正如接受的答案所说,Compose 不会重新计算我的自定义修饰符,因为pointerEvent()没有唯一的键。
@Composable
fun MyApp() {
val myItems = mutableStateListOf("1", "2", "3")
LazyColumn {
items(myItems) { item ->
key(item) { // NEW
MyComponent(item) { toDel -> myItems.remove(toDel) }
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
和
fun Modifier.myClickable(key:Any? = null, delete: () -> Unit) =
pointerInput(key) {
awaitPointerEventScope { awaitFirstDown() }
delete()
}
Run Code Online (Sandbox Code Playgroud)
修复了它,我不需要key()在外部组件中使用。但是,我仍然不确定为什么不需要向 发送唯一密钥clickable {}。
Compose 尝试通过使用键本地化范围来缓存尽可能多的工作:当它们自上次运行以来没有更改时 - 我们正在使用缓存的值,否则我们需要重新计算它。
通过设置key惰性项目,您可以定义内部所有计算的范围remember,并且许多系统功能都是使用它来实现的,remember因此它变化很大。项目索引是惰性项目中的默认键
因此,在删除 first 后item,第一个惰性项目将在与之前相同的上下文中重用
现在我们来谈谈你的myClickable。你Unit作为一个key进入pointerInput(它remember也有一个内部)。通过这样做,您是在向重构器说:在上下文发生变化之前永远不要重新计算该值。并且第一个惰性项的上下文没有改变,例如key仍然是相同的索引,这就是为什么删除的 lambdaitem仍然缓存在该函数内
当您指定惰性项目key等于 时item,您也会更改所有惰性项目的上下文,因此pointerInput会重新计算。如果你通过了你item而不是Unit你将会有同样的效果
因此,当您需要使用时,您key需要使用您的计算不会以不良方式缓存在惰性项目之间
在文档中查看有关惰性列键的更多信息
| 归档时间: |
|
| 查看次数: |
788 次 |
| 最近记录: |