Fragment中控件保存值的问题

今天解决了一个自认为比较棘手的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,观察现象。最终发现问题的关键所在,从而解决问题。

当然,可能还有其他更好的方法,大家如有遇到,烦请告知,谢谢。

浏览 793 次