使用TextWatcher的beforeTextChanged获取EditText旧值时返回null求解决
解决EditText使用TextWatcher获取旧值时返回null的问题
我太懂你这会儿的头疼了——本来想靠beforeTextChanged拿到EditText的旧值,结果每次都碰上个null,完全达不到预期效果。其实这个问题的核心是beforeTextChanged的s参数在某些场景下会为空,直接依赖它并不够稳妥,下面给你两种实用的解决方案:
方案一:手动维护旧值变量
最直观可靠的方式就是自己定义一个变量来存储EditText的当前值,每次文本变化完成后更新这个变量,这样就能精准拿到变化前的旧值:
// 定义变量专门存储EditText的旧值 private var oldNomContent: String = "" val nomTextWatcher: TextWatcher get() = object : TextWatcher { override fun afterTextChanged(s: Editable?) { // 文本变化完成后,更新旧值变量 oldNomContent = s?.toString() ?: "" } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { // 这里的oldNomContent就是文本修改前的旧值 userUpdateSignup.setNom(oldNomContent) } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { s?.toString()?.takeIf { it.isNotEmpty() }?.let { userUpdateSignup.setNom(it) } } } // 别忘了在给EditText设置TextWatcher前,初始化旧值变量 editTextNom.text?.let { oldNomContent = it.toString() }
方案二:通过onTextChanged参数推导旧值
onTextChanged的before参数代表了被替换的字符数量,结合变化后的文本内容,我们可以反向推算出修改前的旧值:
val nomTextWatcher: TextWatcher get() = object : TextWatcher { override fun afterTextChanged(s: Editable?) { } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { // 先处理s可能为null的情况,避免空指针 val oldValue = s?.toString() ?: "" userUpdateSignup.setNom(oldValue) } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { s?.toString()?.takeIf { it.isNotEmpty() }?.let { userUpdateSignup.setNom(it) } // 如果需要在onTextChanged里也拿到旧值,可以这样推导 s?.let { newValue -> val oldValue = if (before > 0) { // 拼接未被修改的前后部分,得到旧值 newValue.subSequence(0, start).toString() + newValue.subSequence(start + count, newValue.length).toString() } else { // 没有被替换的字符,直接取起始位置前的内容 newValue.subSequence(0, start).toString() } // 这里的oldValue就是修改前的文本内容 } } }
重要提醒
一定要注意beforeTextChanged的s参数可能为null,所以必须先做非空判断,不然很容易触发空指针异常。如果只是简单的获取旧值,优先推荐第一种手动维护变量的方案,逻辑更清晰也更不容易出错。
内容的提问来源于stack exchange,提问作者Rahma El Ouni
相关产品推荐
相关产品推荐

