之前在使用Fragment的时候偶尔会有这么一个报错,Can not perform this action after onSaveInstanceState,意思为无法再onSaveInstanceState之后执行该操作,这个操作就是指commit(),之前也没怎么在意,后来通过查看源码去了解了一下这个问题,以下是对这个问题的解析及对应解决办法的对比。
Fragment是我们经常用到的东西,常用的操作有添加(add)、移除(remove)、替换(replace)等,这些操作组成一个集合transaction,我们在通过调用getSupportFragmentManager().beginTransaction()来获取这个FragmentTransaction类的实例来管理这些操作,将他们存进由activity管理的back stack中,这样我们就可以进行fragment变化的回退操作,也可以这样去获取FragmentTransaction类的实例:
- FragmentManager mFragmentManager = getSupportFragmentManager();
- FragmentTransaction mFragmentTransaction = mFragmentManager.beginTransaction();
首先从我们获取FragmentTransaction类的实例开始,即getSupportFragmentManager(),源码是这样的:
- /**
- * Return the FragmentManager for interacting with fragments associated
- * with this activity.
- */
- public FragmentManager getSupportFragmentManager() {
- return mFragments;
- }
- final FragmentManagerImpl mFragments = new FragmentManagerImpl();
- final class FragmentManagerImpl extends FragmentManager {
- ... ...
- @Override
- public FragmentTransaction beginTransaction() {
- return new BackStackRecord(this);
- }
- .... ...
- }
- final class BackStackRecord extends FragmentTransaction implements
- FragmentManager.BackStackEntry, Runnable {
- public BackStackRecord(FragmentManagerImpl manager) {
- mManager = manager;
- }
- public int commit() {
- return commitInternal(false);
- }
- public int commitAllowingStateLoss() {
- return commitInternal(true);
- }
- int commitInternal(boolean allowStateLoss) {
- if (mCommitted) throw new IllegalStateException("commit already called");
- if (FragmentManagerImpl.DEBUG) {
- Log.v(TAG, "Commit: " + this);
- LogWriter logw = new LogWriter(TAG);
- PrintWriter pw = new PrintWriter(logw);
- dump(" ", null, pw, null);
- }
- mCommitted = true;
- if (mAddToBackStack) {
- mIndex = mManager.allocBackStackIndex(this);
- } else {
- mIndex = -1;
- }
- mManager.enqueueAction(this, allowStateLoss);
- return mIndex;
- }
- }
- public void enqueueAction(Runnable action, boolean allowStateLoss) {
- if (!allowStateLoss) {
- checkStateLoss();
- }
- synchronized (this) {
- if (mActivity == null) {
- throw new IllegalStateException("Activity has been destroyed");
- }
- if (mPendingActions == null) {
- mPendingActions = new ArrayList<Runnable>();
- }
- mPendingActions.add(action);
- if (mPendingActions.size() == 1) {
- mActivity.mHandler.removeCallbacks(mExecCommit);
- mActivity.mHandler.post(mExecCommit);
- }
- }
- }
- 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);
- }
- }
长篇大论终于讲完了,其实回头一看并没有多么复杂,就跟着源码一步一步去找,就会找到我们发生错误的地方,看了源码之后发现,原来并没有多么难,so easy!哈哈