前面一次项目中遇到了这个问题,后来解决了,这次项目中又遇到了这个问题,结果困扰了我一天,问了下同事,茅塞顿开。
所以写下来记住。
android有个监听输入的接口:TextWatcher,自己可以实现它,然后让EditText注册。
class Watcher implements TextWatcher{
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
if(isChanged){
return ;
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
mEditView.setText(ss);
}
}
假如按照上面所写的,一定会产生bug:StackOverflowError
原因是setText()本身就会回调监听器,监听器里面after函数有调用setText,结果就是一个没有出口的相互调用,结果是调用函数堆栈溢出。
解决办法有:不要在监听器里写触发监听器的函数,特别是没有出口的函数相互调用。
第二:可以写一个标志位:flag,假如EditText内容发生变化,才让他执行setText函数,如果没有发生变化,就不执行监听器里的setText函数
:class Watcher implements TextWatcher{
private boolean isChanged = false;
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
if(isChanged){
return ;
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
if(isChanged){
return ;
}
String str = s.toString();
SpannableString ss = ChatEmotion.string2Symbol(SmileActivity.this, str);
Log.d(TAG, ss.toString());
isChanged = true;
mEditView.setText(ss);
isChanged = false;
mEditView.invalidate();
}
}
这样就ok啦,哈哈,set之前将标志位置true,之后将标志位置false