Я хочу понять, почему ссылка на объект состояния изменилась в updateCfg, но она по-прежнему не запускает рекомпозицию .
Этот объект состояния является нестабильным типом, поэтому он должен инициировать рекомпозицию при изменении ссылки, верно? Перед назначением в updateCfg _jsonCfg.value и cfg имеют равные значения, а элемент настроек ссылается на один и тот же список. Перед заданием я распечатал их хеш-коды, а они разные.
Код: Выделить всё
@Composable
fun Parents(viewModel: MyViewModel) {
val cfg by viewModel.jsonCfg.observeAsState()
val state by viewModel.stateCfg.collectAsState()
Column {
cfg?.let {
Text(text = "livedata Size:${cfg!!.list.size}")
ChildComposableFunc(cfg!!) { newList ->
viewModel.updateCfg(cfg!!.copy(list = newList))
}
}
HorizontalDivider()
//
Text(text = "State Size:${state.list.size}")
ChildComposableFunc(state) { newList ->
viewModel.updateState(state.copy(list = newList))
}
}
}
@Composable
fun ChildComposableFunc(
cfg: MyConfig,
onCfgChange: (MutableList) -> Unit
) {
Button(onClick = {
cfg.list.removeAt(0)
onCfgChange(cfg.list)
}) {
Text(text = "Sub!")
}
}
data class MyConfig(
var name: String,
var list: MutableList
) {
}
class MyViewModel(inCfg: MyConfig) : ViewModel() {
// LiveData 实现数据变化的自动通知和 UI 的更新
val jsonCfg: LiveData
get() = _jsonCfg
private val _jsonCfg = MutableLiveData(inCfg)
private val _stateCfg = MutableStateFlow(inCfg)
val stateCfg = _stateCfg.asStateFlow()
init {
// Log.d("ViewModelLocal", "Create A ViewModelLocal")
// _jsonCfg.value = inCfg
// // 监听 LiveData 变化并记录日志
_jsonCfg.observeForever { newValue ->
Log.d("ViewModelLocal", "LiveData changed: $newValue")
}
//
}
fun updateCfg(cfg: MyConfig) {
Log.d("ViewModelLocal", "updateCfg: ${_jsonCfg.value}")
Log.d("ViewModelLocal", "updateCfg: $cfg")
Log.d("CPKCPK1", "" + System.identityHashCode(_jsonCfg.value))
Log.d("CPKCPK2", "" + System.identityHashCode(cfg))
_jsonCfg.value = cfg
Log.d("CPKCPK1", "" + System.identityHashCode(_jsonCfg.value))
}
fun updateState(cfg: MyConfig) {
_stateCfg.value = cfg
}
}
Следующий код работает нормально, но вам просто нужно изменить функцию ChildComposableFunc. Создав резервную копию списка для работы, вы можете запустить рекомпозицию. В этом случае присвоение в updateCfg и updateState будет двумя разными значениями.
Код: Выделить всё
@Composable
fun ChildComposableFunc(
cfg: MyConfig,
onCfgChange: (MutableList) -> Unit
) {
val tmpList = cfg.list.toMutableList()
Button(onClick = {
// cfg.list.removeAt(0)
tmpList.removeAt(0)
onCfgChange(tmpList)
}) {
Text(text = "Sub!")
}
}
Подробнее здесь: https://stackoverflow.com/questions/790 ... er-compose
Мобильная версия