原文地址:http://lihb.github.io/%E5%85%B3%E4%BA%8Efragment%E7%9A%84%E4%B8%80%E4%B8%AA%E9%97%AE%E9%A2%98/
关于fragment的一个问题
2015-11-11
今天解决了一个自认为比较棘手的bug。特别记录在此。
背景: 该界面是一个fragment,fragment中有一个EditText控件。出现的问题是,我第一次进入该fragment,
在edittext控件输入内容,然后返回到该fragemnt之前的界面,
接着再次返回到该fragmen界面时,之前在edittext中输入的内容又重新出现在该edittext中。很是奇葩!!!
解决方法:经过数小时的打log,debug之后,本人发现在fragment的生命周期中,如果你只是退出该fragment,
而没有销毁之。fragment会在其生命周期的onViewStateRestored()中,
会重新给edittext控件 setText(),并赋上原来的内容。也就是说,fragment自己保存了控件的一些状态和属性信息。
如果你不想保留原来的值,最好覆写onViewStateRestored()方法,
并在其调用super.onViewStateRestored()之前,抢先调用edittext的setText()方法,亦即覆盖掉fragment中保存的edittext的内容。如下所示:
@Override
public void onViewStateRestored(Bundle savedInstanceState) {
mEditText.setText("");
super.onViewStateRestored(savedInstanceState);
}
这样就能解决edittext内容还魂的bug。
但是:当我们在fragment中为这个edittext控件增加一个TextWatcher接口,如下所示:
mEditText.addTextChangedListener(mTextWatcher);
private TextWatcher mTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable editable) {
if(editable.length() > 0)
Log.i("log test.......", "我被执行了");
}
};
新的问题又来了。再次进入该fragment时,虽然edittext控件中,没有上次进入填写的内容,
但是afterTextChanged()方法中的log语句被打印出来了。也就是说,虽然edittext中的内容清空了。
但是,mTextWatcher中缓存了一份edittext内容,在重新进入fragment,fragment恢复界面的时候,
当执行到mEditText.addTextChangedListener(mTextWatcher)语句时,mTextWatcher缓存的上次的内容又出来
了,导致log语句被打印出来了。。。。。
解决办法:经过调试,观察fragment的生命周期的先后执行顺序。本人发现打印log语句的时候时间是在生命周期的onResume()方法之前。
于是,就想能不能在通过一个变量控制,并把该变量添加到if语句的判断条件中去,
当代码运行到onResume()之前,该变量值为false;在运行到onResume()方法之后,该变量指变为true。从而控制log语句的打印。
于是试了下,该方法的确可行。进而,本人又从源码中发现,fragment中有个booelan isResumed()
方法,
根据此方法的返回值,即可判断是当前代码是运行到onResume()方法之前还是之后。于是最终修改后的代码如下:
@Override
public void onViewStateRestored(Bundle savedInstanceState) {
mEditText.setText("");
super.onViewStateRestored(savedInstanceState);
}
......
mEditText.addTextChangedListener(mTextWatcher);
private TextWatcher mTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable editable) {
if(editable.length() > 0 && isResumed())
Log.i("log test.......", "我被执行了");
}
};
总结:解决问题的方法,不断的调试,在你任何怀疑的地方,输出log,观察现象。最终发现问题的关键所在,从而解决问题。
当然,可能还有其他更好的方法,大家如有遇到,烦请告知,谢谢。