Jetpack Compose单位转换器MVVM架构:无法输入及切换单位
问题根源分析
你的代码核心问题在于ViewModel的状态与Repository的数据完全脱节,且计算逻辑中存在状态覆盖:
- 在UI中修改
viewModel.inputValue.value或切换下拉菜单时,仅更新了ViewModel的MutableState,但Repository里的_data并未同步更新。 - 调用
viewModel.calculation()时,Repository使用自身存储的旧数据计算,之后又将旧数据重新赋值给ViewModel状态,直接覆盖了你在UI中做的所有修改,导致输入和下拉选择无法生效。
解决方案
重构代码,让ViewModel直接管理UI状态,Repository仅负责纯计算逻辑(不存储状态),避免状态同步混乱。
1. 重构UnitRepository
修改Repository,使其仅接收计算所需参数并返回结果,不再存储任何状态:
package com.bank.unitconverter import kotlin.math.roundToInt data class UnitModel( var inputValue: String, var inputUnit: String, var outputValue: String, var outputUnit: String, var iExpanded: Boolean, var oExpanded: Boolean, var conversionFactor:Double, var oconversionFactor:Double ) class UnitRepository{ // 仅负责计算逻辑,接收参数并返回结果 fun calculateUnit(inputValue: String, conversionFactor: Double, oconversionFactor: Double): String { val inputValueDouble = inputValue.toDoubleOrNull() ?: 0.00 val result = (inputValueDouble * conversionFactor * 100.0 / oconversionFactor).roundToInt() / 100.0 return result.toString() } }
2. 重构UnitViewModel
让ViewModel直接管理所有UI状态,调用Repository时传入当前状态参数,避免状态覆盖:
package com.bank.unitconverter import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel class UnitViewModel: ViewModel(){ private val _repository: UnitRepository = UnitRepository() // 直接定义可观察状态,初始值与原逻辑一致 val inputValue = mutableStateOf("") val outputValue = mutableStateOf("") val inputUnit = mutableStateOf("Meters") val outputUnit = mutableStateOf("Meters") val iExpanded = mutableStateOf(false) val oExpanded = mutableStateOf(false) val conversionFactor = mutableStateOf(1.0) val oconversionFactor = mutableStateOf(1.0) fun calculation(){ // 传入当前状态给Repository计算,更新结果状态 outputValue.value = _repository.calculateUnit( inputValue.value, conversionFactor.value, oconversionFactor.value ) } }
3. 优化UI文本一致性(可选)
注意到DropdownMenuItem中的文本是"Centimeter",但设置的单位是"Centimeters",统一文本避免显示不一致:
// 示例:修改输入单位下拉项文本 DropdownMenuItem(text = { Text("Centimeters") }, onClick = { viewModel.iExpanded.value = false viewModel.inputUnit.value = "Centimeters" viewModel.conversionFactor.value = 0.01 viewModel.calculation() })
验证效果
修改完成后:
- 在OutlinedTextField输入数值时,
inputValue状态实时更新,调用calculation()后会正确计算并更新outputValue。 - 切换下拉菜单时,对应的单位和转换系数状态更新,计算结果同步变化。
内容的提问来源于stack exchange,提问作者Bhanu Pratap
相关产品推荐
相关产品推荐

