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

为两个EditText设置TextChangedListener致应用崩溃问题求助

解决EditText双向监听导致的循环崩溃问题

问题原因

你遇到的崩溃是因为双向文本监听触发了无限循环:

  • 当monayValueEditText1输入内容时,其文本变化监听器会修改monayValueEditText2的文本
  • 这又会触发monayValueEditText2的文本变化监听器,反过来修改monayValueEditText1的文本
  • 如此往复,不断调用setText(),最终导致栈溢出(StackOverflowError),应用崩溃

解决方案

核心思路是添加一个标记位,区分文本变化是用户输入还是代码主动设置,避免触发循环逻辑。以下是修改后的代码:

private fun initListener() {
    var money = 0.0
    // 标记位:判断当前是否是代码设置文本,避免触发循环监听
    var isSettingText = false
    binding.apply {
        monayValueEditText1.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}

            override fun afterTextChanged(s: Editable?) {
                if (isSettingText) return // 代码设置文本时跳过监听逻辑
                val money1position = moneyValueSpinner1.selectedItemPosition
                val money2position = moneyValueSpinner2.selectedItemPosition
                
                // 安全处理空输入和非数字输入
                money = s?.toString()?.toDoubleOrNull() ?: 0.0
                // 安全处理currencyList中的空值,避免空指针
                val currency1 = currencyList.getOrNull(money1position) ?: return
                val currency2 = currencyList.getOrNull(money2position) ?: return
                val forexBuying1 = currency1.ForexBuying ?: 0.0
                val unit1 = currency1.Unit?.toDoubleOrNull() ?: 1.0
                val forexBuying2 = currency2.ForexBuying ?: 0.0
                val unit2 = currency2.Unit?.toDoubleOrNull() ?: 1.0

                val result = ((forexBuying1 / unit1) * money) / forexBuying2 / unit2
                
                // 设置标记,避免触发另一个EditText的监听
                isSettingText = true
                monayValueEditText2.setText(DecimalFormat("##.####").format(result).toString())
                isSettingText = false // 恢复标记
            }
        })

        monayValueEditText2.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}

            override fun afterTextChanged(s: Editable?) {
                if (isSettingText) return
                val money1position = moneyValueSpinner1.selectedItemPosition
                val money2position = moneyValueSpinner2.selectedItemPosition
                
                money = s?.toString()?.toDoubleOrNull() ?: 0.0
                val currency1 = currencyList.getOrNull(money1position) ?: return
                val currency2 = currencyList.getOrNull(money2position) ?: return
                val forexBuying1 = currency1.ForexBuying ?: 0.0
                val unit1 = currency1.Unit?.toDoubleOrNull() ?: 1.0
                val forexBuying2 = currency2.ForexBuying ?: 0.0
                val unit2 = currency2.Unit?.toDoubleOrNull() ?: 1.0

                val result = ((forexBuying2 / unit2) * money) / forexBuying1 / unit1
                
                isSettingText = true
                monayValueEditText1.setText(DecimalFormat("##.####").format(result).toString())
                isSettingText = false
            }
        })
    }
}

额外优化点

  • 替换!!强制非空断言为安全调用?:,避免空指针异常
  • 使用toDoubleOrNull()替代toDouble(),处理用户输入非数字的情况
  • 用getOrNull()获取列表元素,防止索引越界

内容的提问来源于stack exchange,提问作者Ömer Seyfettin Yavuzyiğit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 08:00:57