如果它是 Jetpack Compose 中 class 的实例,如何通知状态更改
How to notify about state change if it is an instance of a class in jetpack compose
我有这样的代码:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
TestsTheme {
var myvalue = remember{ mutableStateOf(4)}
Row() {
CustomText(myvalue = myvalue)
CustomButton(myvalue = myvalue)
}
}
}
}
}
@Composable
fun CustomButton(myvalue: MutableState<Int>) {
Button(onClick = {myvalue.value++}) {
}
}
@Composable
fun CustomText(myvalue: MutableState<Int>) {
Text("${myvalue.value}")
}
当我单击 CustomButton 时,CustomText 会重新组合并更改它的值(这没问题),但是如果我用某个 class 的对象替换 myvalue,它就不起作用
如果 myvalue 现在是 TestClass 的一个实例并且它在下面的代码中发生了变化,我该如何重新组合 CustomText?
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
TestsTheme {
var myvalue = remember{ mutableStateOf(TestClass(4))}
Row() {
CustomText(myvalue = myvalue)
CustomButton(myvalue = myvalue)
}
}
}
}
}
@Composable
fun CustomButton(myvalue: MutableState<TestClass>) {
Button(onClick = {myvalue.value.a++}) {
}
}
@Composable
fun CustomText(myvalue: MutableState<TestClass>) {
Text("${myvalue.value.a}")
}
data class TestClass(var a: Int) {
}
Compose 只能理解如果你设置了一个 State
对象的值它应该重新组合。在您的示例中,myvalue.value++
实际上只是 myvalue.value = myvalue.value.inc()
的缩写,因此触发重组的是调用 state.value
setter。
如果你只是改变一个状态持有的对象的 属性,你就不会调用 setter 并且不会发生重组。
所以你有 2 个选项来解决这个问题:
- 使
TestClass
不可变并使用新对象更新 State
data class TestClass(val a: Int) { // << changed var to val
}
@Composable
fun CustomButton(myvalue: MutableState<TestClass>) {
Button(onClick = {
val current = myvalue.value
myvalue.value = current.copy(a = current.a + 1)
}) {
}
}
这不是很好读,但不需要 TestClass
包含任何 compose-specific 代码。
- 使
TestClass
成为国家持有者
class TestClass(a: Int) {
var a by mutableStateOf(a)
}
@Composable
fun Parent(){
val myvalue = remember{ TestClass(4) } // no mutableStateOf, state is managed inside the object
CustomButton(myvalue = myvalue)
}
@Composable
fun CustomButton(myvalue: TestClass) {
Button(onClick = { myvalue.a++ }) {
}
}
我有这样的代码:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
TestsTheme {
var myvalue = remember{ mutableStateOf(4)}
Row() {
CustomText(myvalue = myvalue)
CustomButton(myvalue = myvalue)
}
}
}
}
}
@Composable
fun CustomButton(myvalue: MutableState<Int>) {
Button(onClick = {myvalue.value++}) {
}
}
@Composable
fun CustomText(myvalue: MutableState<Int>) {
Text("${myvalue.value}")
}
当我单击 CustomButton 时,CustomText 会重新组合并更改它的值(这没问题),但是如果我用某个 class 的对象替换 myvalue,它就不起作用
如果 myvalue 现在是 TestClass 的一个实例并且它在下面的代码中发生了变化,我该如何重新组合 CustomText?
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
TestsTheme {
var myvalue = remember{ mutableStateOf(TestClass(4))}
Row() {
CustomText(myvalue = myvalue)
CustomButton(myvalue = myvalue)
}
}
}
}
}
@Composable
fun CustomButton(myvalue: MutableState<TestClass>) {
Button(onClick = {myvalue.value.a++}) {
}
}
@Composable
fun CustomText(myvalue: MutableState<TestClass>) {
Text("${myvalue.value.a}")
}
data class TestClass(var a: Int) {
}
Compose 只能理解如果你设置了一个 State
对象的值它应该重新组合。在您的示例中,myvalue.value++
实际上只是 myvalue.value = myvalue.value.inc()
的缩写,因此触发重组的是调用 state.value
setter。
如果你只是改变一个状态持有的对象的 属性,你就不会调用 setter 并且不会发生重组。
所以你有 2 个选项来解决这个问题:
- 使
TestClass
不可变并使用新对象更新State
data class TestClass(val a: Int) { // << changed var to val
}
@Composable
fun CustomButton(myvalue: MutableState<TestClass>) {
Button(onClick = {
val current = myvalue.value
myvalue.value = current.copy(a = current.a + 1)
}) {
}
}
这不是很好读,但不需要 TestClass
包含任何 compose-specific 代码。
- 使
TestClass
成为国家持有者
class TestClass(a: Int) {
var a by mutableStateOf(a)
}
@Composable
fun Parent(){
val myvalue = remember{ TestClass(4) } // no mutableStateOf, state is managed inside the object
CustomButton(myvalue = myvalue)
}
@Composable
fun CustomButton(myvalue: TestClass) {
Button(onClick = { myvalue.a++ }) {
}
}