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

Kotlin度量转换APP崩溃排查:when表达式UI显示问题求助

度量转换APP崩溃与when表达式问题排查及修复

问题根源分析

  1. 重复布局加载:onCreate中连续调用两次setContentView,第一次加载原始布局,第二次加载ViewBinding根布局,导致布局绑定混乱,易引发空指针或视图异常。
  2. 无限递归栈溢出:convertMetric方法最后一行递归调用自身,形成无限循环触发栈溢出,直接导致APP崩溃。
  3. 错误的条件判断逻辑:用位运算and组合两个RadioButton的ID,这不是判断“选中A且选中B”的正确方式——位运算会篡改ID数值,导致分支永远匹配不到,出现“分支不可达”提示。
  4. 未处理非法输入:直接将输入框文本转Double,若输入为空或非数字,会抛出NumberFormatException导致崩溃。
  5. 计算结果丢失:每个when都是独立代码块,计算结果未赋值给变量直接被丢弃,最终无法显示转换结果。

修复步骤及代码修正

1. 修复布局加载问题

移除onCreate中重复的setContentView(R.layout.activity_main),仅保留ViewBinding的布局加载:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root) // 仅保留这一行
    binding.conversionTo.setOnClickListener { convertMetric() }
}

2. 消除递归并保存计算结果

将convertMetric改为计算结果后直接赋值,避免递归调用自身:

  • 定义变量存储转换结果
  • 用Pair(selectedId, selectedId2)作为when的判断对象,合并所有分支到一个when中

3. 添加输入校验

在转换前判断输入合法性,避免转换异常:

val stringInTextField = binding.howMuchStuffWeTalking.text.toString().trim()
if (stringInTextField.isEmpty()) {
    binding.metricConverted.text = getString(R.string.please_enter_value)
    return
}
val amountIQ = try {
    stringInTextField.toDouble()
} catch (e: NumberFormatException) {
    binding.metricConverted.text = getString(R.string.invalid_input)
    return
}

4. 修正when表达式逻辑

用Pair组合两个选中的RadioButton ID,统一处理所有转换分支,并添加默认分支覆盖未定义的转换组合:

val result = when (Pair(selectedId, selectedId2)) {
    Pair(R.id.Grain, R.id.Ounce1) -> amountIQ / 437.5
    Pair(R.id.Grain, R.id.quarter1) -> amountIQ * 0.000005714
    Pair(R.id.Grain, R.id.pound1) -> amountIQ * 0.0001429
    Pair(R.id.Grain, R.id.Ton1) -> amountIQ / 1.4e+7
    Pair(R.id.Grain, R.id.stone1) -> amountIQ * 0.0000102
    else -> {
        binding.metricConverted.text = getString(R.string.unsupported_conversion)
        return
    }
}
binding.metricConverted.text = getString(R.string.end_result, result)

完整修正代码

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(binding.root)
        binding.conversionTo.setOnClickListener { convertMetric() }
    }

    fun convertMetric() {
        val stringInTextField = binding.howMuchStuffWeTalking.text.toString().trim()
        // 输入校验
        if (stringInTextField.isEmpty()) {
            binding.metricConverted.text = getString(R.string.please_enter_value)
            return
        }
        val amountIQ = try {
            stringInTextField.toDouble()
        } catch (e: NumberFormatException) {
            binding.metricConverted.text = getString(R.string.invalid_input)
            return
        }

        val selectedId = binding.unitThatNeedsToBeConverted.checkedRadioButtonId
        val selectedId2 = binding.toBeConverted.checkedRadioButtonId

        // 处理未选中RadioButton的情况
        if (selectedId == -1 || selectedId2 == -1) {
            binding.metricConverted.text = getString(R.string.please_select_units)
            return
        }

        // 统一的when表达式处理转换逻辑
        val result = when (Pair(selectedId, selectedId2)) {
            Pair(R.id.Grain, R.id.Ounce1) -> amountIQ / 437.5
            Pair(R.id.Grain, R.id.quarter1) -> amountIQ * 0.000005714
            Pair(R.id.Grain, R.id.pound1) -> amountIQ * 0.0001429
            Pair(R.id.Grain, R.id.Ton1) -> amountIQ / 1.4e+7
            Pair(R.id.Grain, R.id.stone1) -> amountIQ * 0.0000102
            else -> {
                binding.metricConverted.text = getString(R.string.unsupported_conversion)
                return
            }
        }

        binding.metricConverted.text = getString(R.string.end_result, result)
    }
}

额外优化建议

  • 在strings.xml中添加对应提示字符串(如please_enter_value、invalid_input等),避免硬编码文本
  • 为RadioButton组设置默认选中项,减少用户未选中时的提示场景
  • 后续扩展其他单位转换时,只需在when中添加新的Pair分支即可

内容的提问来源于stack exchange,提问作者codingNoob

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 15:45:42