上周在实现一个功能的时候遇到了很多问题,然后折腾了好久才解决,以防今后又遇上同样的问题特在此记录下。
我实现的功能要求是一个界面上有四个EditText控件,其中任意一个内容变化,其他三个都要根据算法做出相应变化,这就牵扯到了多个EditText相互监听的问题了。
要实现EditText的监听就会用到TextWatcher;
首先我们来了解一下TextWatcher的用法吧!
TextWatcher myWatcher = newTextWatcher(){ @Override public void onTextChanged(CharSequence s,int start,int before,int count){ System.out.println("onTextChanged"); System.out.println("s = "+s+",start = "+start+",before = "+before+",count = "+count); } @Override public void beforeTextChanged(CharSequence s,int start,int count,int after){ System.out.println("beforeTextChanged"); System.out.println("s = "+s+",start = "+start+",count = "+count+",after = "+after); } @Override public void afterTextChanged(Editable s){ System.out.println("afterTextChanged"); System.out.println("s = " + s); } };大家可以根据各参数打印出来的结果了解参数具体指什么;
问题一:
接下来当我最初开始使用edittext的TextWatcher,运行程序时出现了java.lang.StackOverflowError错误,
经过分析知道,每次使用setText()方法为EditText添加数据时,会重新触发监听器,并不断的进行递归,造成死循环,最后程序崩溃。
针对这个,我试了两种解决方案:
1. 设置一个flag, 例:
private boolean autochange = false;
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(autochange) { // skip execution if triggered by code
autochange=false; // next change is not triggered by code
return;
}
if (s.length() != 0) {
switch (et.getId()) {
case R.id.etUsername: {
}
break;
case R.id.etPassword: {
phone = formatPhoneNumber(phone);
Log.i("PHONE", "Phone NUMB IS:"+phone);
autochange=true;
mPassword.setText(phone);
}
}
}
}
2. 每次设置文本的时候移除原来的监听,然后再重置一个监听:
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//Toast.makeText(getApplicationContext(), "In onTextChanged() Method", Toast.LENGTH_SHORT).show();
if (s.length() != 0) {
switch (et.getId()) {
case R.id.etUsername: {
}
break;
case R.id.etPassword: {
mPassword.removeTextChangedListener(theWatcher);
phone = formatPhoneNumber(phone);
Log.i("PHONE", "Phone NUMB IS:"+phone);
mPassword.setText(phone); //THE ERROR HAPPENS HERE
mPassword.addTextChangedListener(theWatcher);
}
}
}
}
问题二:
错误:android.content.res.Resources$NotFoundException
原因:一般发生在参数 int resId 错误,你把String赋值给int的resId,所以编译器找不到正确的resource于是报错。
检查一下edittext.setText之类的函数,这种函数通常有几个重载,如:
editText.setText(CharSequence text);
editText.setText(int resId);
......
如果不小心将一个int值传给了它,那它不会显示该int值,而是跑到工程下去找一个对应的resource的id,当然是找不到的,于是就报错啦。
解决办法是使用String.valueOf,例:count.setText(String.valueOf(incall.getCount()));
问题三:
多个EditText相互监听死循环:可以在每个EditText聚焦时再监听其文本变化,即先给edittext设置setOnTouchListener, 然后在此下面进行TextWatcher.