试图在kotlin的ui上获得一个when表达式来显示结果



我制作这个度量转换器应用程序已经有一个多星期了,我一直在回到以前的代码实验室,解释如何制作小费计算器,但当我试图将相同的方法应用于我正在尝试制作的应用程序时,它没有任何错误,但每当我试图测试它以查看是否能使功能正常工作时,应用程序就会崩溃,这是我的最后手段。我曾尝试过执行when语句,但我一直收到错误,即某些分支永远无法到达。如果有人能给我指明正确的方向,告诉我我做错了什么,或者我的代码中缺少了什么。我洗耳恭听。

package com.example.metricconversion
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.metricconversion.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(R.layout.activity_main)
setContentView(binding.root)
binding.conversionTo.setOnClickListener { convertMetric() }
}

fun convertMetric() {
val stringInTextField = binding.howMuchStuffWeTalking.text.toString()
val amountIQ = stringInTextField.toDouble()
val selectedId = binding.unitThatNeedsToBeConverted.checkedRadioButtonId
val selectedId2 = binding.toBeConverted.checkedRadioButtonId
// val grainToQtr = R.id.Grain and R.id.quarter1
//val grainToSt= R.id.Grain and R.id.quarter1
//val grainToLb = R.id.Grain and R.id. pound1
//val grainToTon= R.id.Grain and R.id.Ton1
val st = R.id.Grain and R.id.stone1

// code to convert grain to the other options
//code to convert grain to the other options
when (selectedId and selectedId2) {
R.id.Grain and R.id.Ounce1 -> {
amountIQ / 437.5
}

}
when (selectedId and selectedId2) {
R.id.Grain and R.id.quarter1 -> amountIQ * 0.000005714
}
when (selectedId and selectedId2) {
R.id.Grain and R.id.pound1 -> amountIQ * 0.0001429
}
when (selectedId and selectedId2) {
R.id.Grain and R.id.Ton1 -> amountIQ / 1.4e+7
}
when (selectedId and selectedId2) {
st -> {
amountIQ * 0.0000102
}
}
binding.metricConverted.text=getString(R.string.end_result,convertMetric())
}
}

代码问题:

  1. 使用and同时检查两个值是否相等是不可行的。and函数执行逐位运算以将两个数字合并在一起。有许多可能的输入可以合并到同一个解决方案中,因此您会得到误报。相反,您可以使用to中缀函数将这两个数字组合到一个Pair包装对象中,以便将它们都保留下来进行比较。

  2. 您有一系列单独的when语句,每个语句只有一个条件。将when语句与单个条件一起使用是没有意义的。通常,单个条件将用if语句而不是when语句来表示。但根据我所看到的情况,我猜你并不是有意将这些陈述分开的。

  3. 你的when语句实际上并没有起到任何作用。他们的分支解析为一个数字,但你没有对这个数字做任何事情(没有将它分配给变量、记录它或在UI中显示它,等等(。所以他们没有用。底部的语句没有得到任何when语句的结果,而是再次递归调用同一个函数。这个函数不返回任何内容,所以没有用。即使它确实返回了一个数字,递归调用也会创建一个无限循环,导致堆栈溢出。

因此,首先,只需修复您的代码(我们稍后可以讨论更好的方法(:

  1. 我们用to代替and
  2. 我们将所有when语句合并为一个语句
  3. 我们将when语句的结果存储在一个变量中,并使用该变量设置函数最后一行的文本。当您将when语句与主题(括号中的某个内容,用于比较每个分支(一起使用时,或者为了获得结果,您必须涵盖所有可能的情况,因此还必须添加else分支
fun convertMetric() {
val stringInTextField = binding.howMuchStuffWeTalking.text.toString()
val amountIQ = stringInTextField.toDouble()
val selectedId = binding.unitThatNeedsToBeConverted.checkedRadioButtonId
val selectedId2 = binding.toBeConverted.checkedRadioButtonId
// code to convert grain to the other options
val result = when (selectedId to selectedId2) {
R.id.Grain to R.id.Ounce1 -> amountIQ / 437.5
R.id.Grain to R.id.quarter1 -> amountIQ * 0.000005714
R.id.Grain to R.id.pound1 -> amountIQ * 0.0001429
R.id.Grain to R.id.Ton1 -> amountIQ / 1.4e+7
R.id.Grain to R.id.stone1 -> amountIQ * 0.0000102
else -> error("Unsupported selection pair")
}
binding.metricConverted.text = getString(R.string.end_result, result.toString())
}

上面,error()调用将使您的应用程序崩溃。你需要确保你涵盖了所有可能发生的组合。在开发过程中,这是合适的,但对于生产,您可能需要更改行为,使其在应用程序的UI中显示错误消息,并且不会崩溃。

现在,就整体设计而言,它相当脆弱,因为UI布局细节与应用程序的行为紧密相连。所有这些公式计算可能都应该在一个单独的类中定义,可能是一个Enum类。您可以在"活动"文件中创建一个映射,将UI元素链接到行为类,然后在when语句中,您可以使用UI元素从映射中提取关联的行为。这将更易于维护,并使您在添加/修改功能时更容易避免忘记某些内容。我这么说只是想让你思考一下,但对于现在的初学者来说,这可能太多了。我没有时间详细解释我将如何为你的案件做这一切。

最新更新