Geek的专栏

--------------------------------一切事情到了最后都是好的,如果不好,说明还没到最后!...

BackStackRecord(继承自FragmentTransaction) 中commit()与commitAllowingStateLoss()的区别
    @Override
    public int commit() {
        return commitInternal(false);
    }

    @Override
    public int commitAllowingStateLoss() {
        return commitInternal(true);
    }

从源代码来看,它们调用了同一个方法只是传递的参数不同,那么就是这个参数导致的不同了,继续往下看,

int commitInternal(boolean allowStateLoss) {
        .......
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
}
public void enqueueAction(OpGenerator action, boolean          allowStateLoss) {
        if (!allowStateLoss) {
            checkStateLoss();
        }
        ........
}
private void checkStateLoss() {
     if (mStateSaved) {
         throw new IllegalStateException(
             "Can not perform this action after onSaveInstanceState");
     }
     if (mNoTransactionsBecause != null) {
         throw new IllegalStateException(
              "Can not perform this action inside of " + mNoTransactionsBecause);
     }
}
  1. 不同点出现了,在最后倒数第二段代码中,当allowStateLoss为false的时候,会执行checkStateLoss方法,对应commit方法;当allowStateLoss为true的时候,不会执行checkStateLoss方法,而checkStateLoss又干了什么呢???
  2. 在checkStateLoss中通过mStateSaved字段判断fragment状态是否保存。如果保存就会异常。也就是在执行commit方法时如果状态保存,就异常;什么状态呢???
  3. 就是在Activity异常退出时候,执行的onSaveInstanceState方法保存的状态。在onSaveInstanceState方法中会调用FragmentManager中的saveAllState方法保存fragment的状态

    总结:官方文档
    使用的 commit方法是在Activity的onSaveInstanceState()之后调用的,这样会出错,因为onSaveInstanceState方法是在该Activity即将被销毁前调用,来保存Activity数据的,如果在保存完状态后再给它添加Fragment就会出错。解决办法就是把commit()方法替换成 commitAllowingStateLoss()就行了,其效果是一样的。


什么时候调用onSaveInstanceState()方法呢???
(1)用户主动按下home 键,系统不能确认activity 是否会被销毁,实际上此刻系统也无法预测将来的场景,比如说内存占用,应用运行情况等,所以系统会调用onSaveInstanceState保存activity状态 ;
(2)activity位于前台,按下电源键,直接锁屏;
(3)横竖屏切换;
(4)activity B启动后位于activity A之前,在某个时刻activity A因为系统回收资源的问题要被kill掉,A通过onSaveInstanceState保存状态。


该异常解决
(1)在activity生命周期函数内谨慎使用commit 方法 ,一般情况下如果能在onCreate 中调用,基本不会出现问题,但是如果在onResume onStart 等方法中调用就需要格外注意,比如说FragmetActivity 的onResume 方法 ,在某些场景下onResume 方法被调用之前,可能依然保存着之前的状态导致异常 。
(2)尽可能避免在一些和生命周期函数异步的方法中调用commit,如AsyncTask 等。
(3)实在没法确定调用时机时,可以用commitAllowingStateLoss 代替 commit ,commitAllowingStateLoss 在状态丢失时不会抛出任何异常,但也正因为如此在一些必须确保状态被保存的场合,最好不要使用 commitAllowingStateLoss 方法。

阅读更多
个人分类: Android
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

BackStackRecord(继承自FragmentTransaction) 中commit()与commitAllowingStateLoss()的区别

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭