Can not perform this action after onSaveInstanceState

java.lang.IllegalStateException

Can not perform this action after onSaveInstanceState

1 android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:4)
2 android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1)
3 android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:12)
4 android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:1)
5 android.support.v4.app.DialogFragment.show(DialogFragment.java:5)

一般出現場景都是開啓一個異步任務 結束之後使用DialogFragment進行展示內容 ,接下來給大家分析下爲何會發生這樣異常,如何避免

public void show(FragmentManager manager, String tag) {
    this.mDismissed = false;
    this.mShownByMe = true;
    FragmentTransaction ft = manager.beginTransaction();
    ft.add(this, tag);
    ft.commit();
}
public int commit() {
    return this.commitInternal(false);
}

在看commistInternal方法

int commitInternal(boolean allowStateLoss) {
    if (this.mCommitted) {
        throw new IllegalStateException("commit already called");
    } else {
        if (FragmentManagerImpl.DEBUG) {
            Log.v("FragmentManager", "Commit: " + this);
            LogWriter logw = new LogWriter("FragmentManager");
            PrintWriter pw = new PrintWriter(logw);
            this.dump("  ", (FileDescriptor)null, pw, (String[])null);
            pw.close();
        }

        this.mCommitted = true;
        if (this.mAddToBackStack) {
            this.mIndex = this.mManager.allocBackStackIndex(this);
        } else {
            this.mIndex = -1;
        }

        this.mManager.enqueueAction(this, allowStateLoss);
        return this.mIndex;
    }
}

這裏參數傳的是false 標示顯示的fragment不允許狀態丟失,接下來看enqueueAction方法

public void enqueueAction(FragmentManagerImpl.OpGenerator action, boolean allowStateLoss) {
    if (!allowStateLoss) {
        this.checkStateLoss();
    }

    synchronized(this) {
        if (!this.mDestroyed && this.mHost != null) {
            if (this.mPendingActions == null) {
                this.mPendingActions = new ArrayList();
            }

            this.mPendingActions.add(action);
            this.scheduleCommit();
        } else if (!allowStateLoss) {
            throw new IllegalStateException("Activity has been destroyed");
        }
    }
}

我們可以看到如果不允許狀態丟失會check一下 在看checkStateLoss方法

private void checkStateLoss() {
    if (this.isStateSaved()) {
        throw new IllegalStateException("Can not perform this action after onSaveInstanceState");
    } else if (this.mNoTransactionsBecause != null) {
        throw new IllegalStateException("Can not perform this action inside of " + this.mNoTransactionsBecause);
    }
}

首先判斷了狀態是否已經報錯 true則拋出異常,在看如何進行判斷的isStateSaved方法

public boolean isStateSaved() {
    return this.mStateSaved || this.mStopped;
}

有兩個表示值mStateSaved 和mStopped 只要有任何一個狀態滿足則返回true

由此可以總結出當activity調用了 onSaveInstanceState方法後或者activity處於stopped狀態時候 使用FragmentManager的FragmentTransaction.commit方法提交拋出這樣"Can not perform this action after onSaveInstanceState"異常 直接導致程序crash

解決方案也就很簡單了 只要保證activity的狀態 不是isStateSaved狀態使用FragmentManager的FragmentTransaction.commit 提交fragment就可以了

ps多看看源碼有助於我們更好的使用系統提供的api

文章有什麼不對的地方大家斧正

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章