java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState


在使用Fragment的過程中,常常會遇到在Activity的onSaveInstanceState方法調用之后,操作commit或者popBackStack而導致的crash.
因為在onSaveInstanceState方法之后的操作狀態可能會丟失,因此Android framework默認會拋出一個異常.
對於commit方法來說,單純避免這個異常很簡單,使用commitAllowingStateLoss方法即可.但是popBackStack以及 popBackStackImmediate也都會檢查state(checkStateLoss),特別需要注意的是Activity的 onBackPressed方法

如果onBackPressed在onSavedInstanceState之后調用,那么就會crash.

onBackPressed的調用時機:

* targetSdkVersion <= 5,在onKeyDown中調用
* targetSdkVersion > 5,在onKeyUp中調用
onSavedInstanceState的調用時機(如果調用的話):

* 一定在onStop之前
* 可能在onPause之前,也可能在onPause與onStop之間
需要注意的是: onSavedInstanceState方法不一定會調用,只有在Activity因為某些原因而被Framework銷毀,並且之后還需要重新創建的情況,才需要調用(例如:旋屏,或者內存不足而回收返回棧中的某些Activity)

舉例:
* Activity A在前台時,屏幕逐漸變暗直至鎖屏,那么A的onSavedInstanceState會被調用
* Activity A start Activity B,Activity A的onSavedInstanceState會被調用
* Activity A因為返回鍵或者finish調用而返回到上一個界面,那么A的onSavedInstanceState不會被調用
因此,當onBackPressed在onSavedInstanceState方法之后調用,就一定會crash.解決方法主要有兩種:

重寫Activity的onSavedInstanceState()方法,並且注釋掉super調用.
這種方法能避免crash,但是它會導致整個Activity的狀態丟失.以DialogFragment為例,正常情況下,顯示的 DialogFragment在旋屏Activity重新創建之后,不需要我們處理,Dialog會自動顯示出來(參見 DialogFragment.onStart()),但是注釋掉Activity的onSavedInstanceState()方法之 后,Fragment狀態丟失,Activity重新創建之后,Dialog也就不會再顯示出來了.

更好且通用的做法:在調用commit,popBackStack以及onBackPressed方法之前,判斷 onSavedInstanceState()方法是否已經執行,並且onResume方法還沒有執行,如果不是,那么直接操作,否則加入到 pending隊列,等待onResumeFragments或者onPostResume之后再執行.

注意:不要在onResume中操作,因為這時候FragmentManager中的mStateSaved依然可能是true.(如果執行順序是 onSavedInstanceState()->onPause()->onResume() 或者 onPause()->onSavedInstanceState()->onResume());

public void endPaintingPager(int index) {
        if (mFirstLevel == PAINTING_PAGER) {
            mFirstLevel = PAINTER_START;
            if (!mIsStateSaved) {
                getSupportFragmentManager().popBackStack();
            } else {
                mPopBackStackRunnable = new Runnable() {
                    @Override
                    public void run() {
                        getSupportFragmentManager().popBackStack();
                    }
                };
            }
        }
    }
@Override
    protected void onPostResume() {
        super.onPostResume();
        if (mPopBackStackRunnable != null) {
            mPopBackStackRunnable.run();
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM