Android Compose中mutableStateOf自定义类修改属性不触发重组问题
问题原因
你的代码没有触发重组的核心原因是对Compose mutableStateOf的监听机制理解有误:
mutableStateOf只会追踪它持有对象的引用变更,不会自动监听所持对象内部可变属性的修改- 你的
ValidationButtonModel所有属性都定义为var可变类型,点击事件中你只是修改了对象内部的属性值,State持有的对象引用从头到尾没有发生变化,Compose完全检测不到状态变更,自然不会触发重组 - 你自定义的
Saver只负责配置变更/进程销毁时的状态保存与恢复,和重组触发逻辑完全无关,加Saver解决不了这个问题。另外你写的Saver本身还有索引越界bug:save时只存入了6个元素(索引范围0~5),restore时却取it[6],实际运行到状态恢复逻辑时会直接崩溃。
解决方案
推荐优先使用官方倡导的不可变状态方案,稳定性最高、维护成本最低:
- 把
ValidationButtonModel的所有属性从var改为val不可变类型,依靠data class的copy()方法实现状态更新:
import android.os.Parcelable import kotlinx.parcelize.Parcelize @Parcelize data class ValidationButtonModel( val title: Int, val contentDescription: Int, val rfidReadingStarted: Boolean, val progression: Float, val read: Int, val expected: Int, ) : Parcelable
- 修改状态时,创建新的对象实例赋值给State,触发引用变更通知:
Button( onClick = { val currentState = validationButtonModelState if (currentState.progression < 1.0f) { // 赋值新对象,State检测到引用变化后自动触发重组 validationButtonModelState = currentState.copy( rfidReadingStarted = true, progression = currentState.progression + 0.1f, read = currentState.read + 1 ) } } ) { Text("INCREMENT") }
- 之前的自定义Saver可以直接删掉,
@Parcelize已经能配合rememberSaveable自动完成状态持久化,不需要额外实现Saver逻辑。
如果你一定要保留可变对象的写法,就需要把类内部每个需要触发重组的属性都委托给mutableStateOf,让Compose能追踪到属性变化,但这种方案需要自行实现状态保存逻辑,无法直接使用@Parcelize,维护成本更高,非必要不推荐。
内容的提问来源于stack exchange,提问作者Z3nk
相关产品推荐
相关产品推荐

