异常
java.lang.IllegalStateException
Can not perform this action after onSaveInstanceState
android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:2053)
android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:2079)
android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:678)
android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:632)
com.xxx.ui.fragment.xxx.a(XXXFragment.java:171)
处理方案
把
transaction.show(toShowFragment).commit();
换成
transaction.show(toShowFragment).commitAllowingStateLoss();
原因
就是因为 不能在onSaveInstanceState
这个方法之后调用commit
方法
为什么commitAllowingStateLoss
可以而commit
不可以
对比两个方法源码
@Override
public int commit() {
return commitInternal(false);
}
@Override
public int commitAllowingStateLoss() {
return commitInternal(true);
}
可以看到就是一个简单的布尔值入参不同,追踪下这个布尔值的最终使用的地方(allowStateLoss
)
public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
if (mDestroyed || mHost == null) {
if (allowStateLoss) {
// This FragmentManager isn't attached, so drop the entire transaction.
return;
}
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
mPendingActions = new ArrayList<>();
}
mPendingActions.add(action);
scheduleCommit();
}
}
可以看到就两处使用到了这个变量值
- 第一处:(异常就是从这个地方抛出的)
private void checkStateLoss() {
if (isStateSaved()) {
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
if (mNoTransactionsBecause != null) {
throw new IllegalStateException(
"Can not perform this action inside of " + mNoTransactionsBecause);
}
}
- 第二处:
if (mDestroyed || mHost == null) {
if (allowStateLoss) {
// This FragmentManager isn't attached, so drop the entire transaction.
return;
}
throw new IllegalStateException("Activity has been destroyed");
}
从上面这些代码看来,两个方法的区别仅仅是是否会抛出异常,并没有更多额外的处理。
那么问题来了,能不能全部都直接使用commitAllowingStateLoss
而不使用commit
,从上面的源码层面来看并没有什么实际影响,使用两个方法主要区别是:
commitAllowingStateLoss
:不校验是否在onSaveInstanceState
之后,不校验是否mDestroyed
,也不校验mHost
(宿主关联工具类)
commit
:和上面相反,会校验上面那些内容,也就是发现已经onSaveInstanceState
或者mDestroyed
,mHost==null
的时候,会抛出异常提示。
所以全部都用commitAllowingStateLoss
的时候在大多数场景是没有什么问题的(并不会影响到正常场景的状态信息保存),只是在可能丢失状态的时候不会给到异常提示。
网友评论