天天看點

DialogFragment 使用時出現IllegalStateException: Can not perform this action after onSaveInstanceState

今天騰訊bugly上面看到了如下的錯誤提示:

DialogFragment 使用時出現IllegalStateException: Can not perform this action after onSaveInstanceState

而這個問題所在的原因是使用的DialogFragment 在使用show方法時出現了問題,即在顯示fragment時執行如下的代碼:

DialogFragment 使用時出現IllegalStateException: Can not perform this action after onSaveInstanceState

異常的原因是commit方法是在Activity的onSaveInstanceState()之後調用的,這樣會出錯,因為onSaveInstanceState方法是在該Activity即将被銷毀前調用來儲存Activity資料的,如果在儲存玩狀态後再給它添加Fragment就會出錯。

解決辦法就是把commit()方法替換成 commitAllowingStateLoss()就行了,其效果是一樣的,那麼檢視DialogFragment 源碼并沒有找到使用commitAllowingStateLoss()的show方法,那麼應該怎麼辦呢?

思索一下:

是否想到可以重寫父類的show方法呢 使用commitAllowingStateLoss() 來替換commit() 方法,然而,發現該方法累不使用了私有變量,這就尴尬了,咋辦,立馬又想到可以使用反射的技術,來修改父類的私有變量,來保證重寫show方法後,其他的狀态合法正常:

代碼如下:

/***
     *
     * @param manager
     * @param tag
     */
    @Override
    public void show(FragmentManager manager, String tag) {
        try {
            Field mDismissed = this.getClass().getSuperclass().getDeclaredField("mDismissed");
            Field mShownByMe = this.getClass().getSuperclass().getDeclaredField("mShownByMe");
            mDismissed.setAccessible(true);
            mShownByMe.setAccessible(true);
            mDismissed.setBoolean(this, false);
            mShownByMe.setBoolean(this, true);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, tag);
        ft.commitAllowingStateLoss();
    }
           

經過測試,目前未發現其他問題,歡迎大家指出不合理的地方