You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose单位转换器MVVM架构:无法输入及切换单位

问题根源分析

你的代码核心问题在于ViewModel的状态与Repository的数据完全脱节,且计算逻辑中存在状态覆盖:

  1. 在UI中修改viewModel.inputValue.value或切换下拉菜单时,仅更新了ViewModel的MutableState,但Repository里的_data并未同步更新。
  2. 调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 05:44:59