[英]I don't understand why Jetpack Compose don't recompose when I change list into a mutableStateOf?
[英]Jetpack compose mutableStateOf list doesn't trigger re-composition when changing property value in list item class
我想我在這里遺漏了 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
數據 class 的問題,請告訴我,我會盡力而為。
讓我們先從 Kotlin 的數據類開始
根據kotlin關於Data Class
的文檔
編譯器自動從主構造函數中聲明的所有屬性派生以下成員:
- equals()/hashCode() 對
- 形式為“User(name=John, age=42)”的 toString()
- componentN() 函數對應於聲明順序中的屬性。
- 復制()。
您的IntWrapper
數據 class 有一個Primary Constructor , class 名稱后面的括號,以及其中聲明的 1 個屬性。
data class IntWrapper(val actualInt: Int = 0) {
var sadProperty: Int = 0
}
這樣,我們可以說,您的IntWrapper
數據 class 有
actualInt
)IntWrapper(actualInt=?)
copy()
function並再次基於文檔:
編譯器僅使用主構造函數中定義的屬性來自動生成函數。 要從生成的實現中排除屬性,請在 class 正文中聲明它:
equals
將僅使用/評估從IntWrapper's
主要構造函數(即actualInt: Int
)聲明的屬性,而sadProperty
被排除在外,因為它位於數據 class 主體的一部分。
現在考慮以下問題:
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
)與兩個IntWrapper
實例不同。
現在轉到Jetpack Compose
,應用我們對數據類的理解,
第一個test
符合data class
的所有內容,它創建了一個具有新值的新 object ,這就是Compose
觸發re-composition
所需要的。
第二個test
不會觸發re-composition
, Compose
仍然看到相同的IntWrapper
實例,因為sadProperty
不是將由數據類的 equals 操作使用的生成組件的一部分。
在 Compose 中,您必須使用以下兩種方法之一才能成功執行重組操作:
1 - 使用 mutableStateListOf(),但是,通過更新列表中項目的值,執行重組操作
2- 使用您發布的自己的方法
但是對於第二種方法,你需要告訴Compose,actualInt發生了變化,所以你需要創建一個新的int實例。
如果你不想這樣做,你需要更多地解釋你的場景,以便我提供更完整的指南
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.