为两个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
相关产品推荐
相关产品推荐

