我想我这里缺少了Jetpack Compose的一个核心概念。当我试图更改可组合文件内部的non-constructor
data class
property
时,遇到了一个问题,而该可组合文件是观察列表的一部分。
不起作用:(sadProperty
未在构造函数中声明(
data class IntWrapper(val actualInt: Int = 0) {
var sadProperty: Int = 0
}
@Preview
@Composable
fun test() {
var state by remember { mutableStateOf(listOf(IntWrapper(1), IntWrapper(2), IntWrapper(3),IntWrapper(4)))}
fun onClick(item: IntWrapper) {
val indexOf = state.indexOf(item)
val newState = state.minus(item).toMutableList()
val copy = item.copy()
copy.sadProperty = Random.nextInt()
newState.add(indexOf, copy)
state = newState
}
Column() {
for (item in state) {
Text("ac: ${item.actualInt} sad: ${item.sadProperty}", modifier = Modifier.clickable { onClick(item)})
}
}
}
作品:(actualInt
在构造函数中声明(
data class IntWrapper(var actualInt: Int = 0) {
var sadProperty: Int = 0
}
@Preview
@Composable
fun test() {
var state by remember { mutableStateOf(listOf(IntWrapper(1), IntWrapper(2), IntWrapper(3),IntWrapper(4)))}
fun onClick(item: IntWrapper) {
val indexOf = state.indexOf(item)
val newState = state.minus(item).toMutableList()
val copy = item.copy()
copy.actualInt = Random.nextInt()
newState.add(indexOf, copy)
state = newState
}
Column() {
for (item in state) {
Text("ac: ${item.actualInt} sad: ${item.sadProperty}", modifier = Modifier.clickable { onClick(item)})
}
}
}
有人能解释一下为什么会发生这种情况吗?
这看起来像是Jetpack Compose
和关于Kotlin
数据类的问题,我会尽力的。
让我们首先从Kotlin的数据类开始
根据关于Data Class
的kotlin文件
编译器自动从所有在主构造函数中声明的属性:
- equals((/hashCode((对
- toString((的形式;用户(姓名=John,年龄=42(">
- componentN((函数,这些函数按声明顺序与属性相对应
- copy((
您的IntWrapper
数据类有一个主构造函数,类名后面的括号,其中声明了1个属性。
data class IntWrapper(val actualInt: Int = 0) {
var sadProperty: Int = 0
}
这样,我们可以说,您的IntWrapper
数据类具有
- 1组分(
actualInt
( - 形式为
IntWrapper(actualInt=?)
的toString(( - 生成的CCD_ 13函数
- 生成的equals((/hashCode((对
并且再次基于文档:
编译器仅使用在主构造函数。排除属性,在类主体:
equals
将仅使用/评估从IntWrapper's
主构造函数(即actualInt : Int
(声明的属性,并且sadProperty
被排除在外,因为它位于数据类主体的部分。
现在考虑以下内容:
val intWrapper1 = IntWrapper(actualInt = 5)
intWrapper1.sadProperty = 5
val intWrapper2 = IntWrapper(actualInt = 5)
intWrapper2.sadProperty = 10
Log.e("AreTheyEqual?", "${intWrapper1 == intWrapper2}")
它打印,
E/AreTheyEqual?: true
因为equality
看到两个导出属性具有相同的值5
,所以sadProperty
被排除在该比较之外。
val intWrapper1 = IntWrapper(actualInt = 5)
intWrapper1.sadProperty = 5
val intWrapper2 = IntWrapper(actualInt = 10)
intWrapper2.sadProperty = 5
打印,
E/AreTheyEqual?: false
因为生成的equals验证生成的组件(actualInt
(与两个CCD_。
现在转到Jetpack Compose
,应用我们对数据类、所了解的一切
第一个
test
符合data class
的所有内容,它创建了一个具有新值的新对象,而这正是Compose
触发re-composition
所需要的。第二个
test
不会触发re-composition
,Compose
仍然看到相同的IntWrapper
实例,因为sadProperty
不是将由数据类的等于运算使用的生成组件的一部分。
在Compose中,必须使用以下两种方法之一才能成功执行重组操作:
1-使用mutableStateListOf((,但是,通过更新列表中项目的值,可以执行重新组合操作
2-使用你自己的方法,你张贴
但对于第二种方法,您需要告诉Compose actualInt已经更改,因此您需要创建一个int的新实例。
如果你不想这样做,你需要更多地解释你的场景,这样我就可以提供一个更完整的指南