Fragment栈操作 commit()分析

fragment 栈操作时遇到一个问题

  supportFragmentManager.beginTransaction()
                .replace(R.id.xxx, xxxFragment)
                .addToBackStack(null).commitNowAllowingStateLoss();

抛出异常:

Caused by: java.lang.IllegalStateException: This transaction is already being added to the back stack
at android.support.v4.app.BackStackRecord.disallowAddToBackStack(BackStackRecord.java:600)
at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:678)

看异常 哦 原来是 已经被 加入栈了,那就去掉 .addToBackStack(null) 这句话 显然 好使了 能正常显示fragment。但是还有一个 就是按返回键 或者 别的操作 要把上一个fragment从 BackStack 中拿出来 。
从fragment的回退栈中取东西 需要用 :supportFragmentManager.popBackStackImmediate();
可是怎么都没法回退, 还真是奇了怪了!

分析:
回退栈中是否有这个fragment

supportFragmentManager.getBackStackEntryCount()这个方法可以查看fragment 回退栈的个数 发现 竟然是 0 看来并没有入站啊
先贴上解决方案

 supportFragmentManager.beginTransaction()
                .replace(R.id.fl_increment_need_info, getNeedInfoFragment(tag))
                .addToBackStack(null).commit();

.addToBackStack(null).commit();这样就没有问题了。
抱着求知的心态 让我们看看 为什么 commitNowAllowingStateLoss这个方法不能 入栈:

首先fragment事物的提交方式有四种:
/**
* 摘出其中的关键点 
* it will be scheduled as work on the main thread
* to be done the next time that thread is ready.
* 不会立即执行 而是通过调度器有序的在主线程被执行 
* 显然是可以被加入back stack
**/
 public abstract int commit();
/**
* 该方法是 commit的加强版 支持在activity非活跃状态下提交事物
**/
public abstract int commitAllowingStateLoss();
/**
* Transactions committed in this way may not be added to the
* FragmentManager's back stack
* 了解到 这个方法 提交的fragment是不会被添加到 FragmentManager's back stack
**/
public abstract void commitNow();
/**
* 1类似commitNow();类似到什么程度呢?就是不会把fragment 加入fragment back stack栈。 看来是个加强版
* 2 the commit can be lost if the activity needs to later be restored from its state,
* 这个方法可以 在activity状态改变之后使用在activity非active状态的情况下是可以提交 并不会报错的
* 了解到 这个方法 提交的fragment是不会被添加到 FragmentManager's back stack
**/
public abstract void commitNowAllowingStateLoss();

切入点 1 异常点 2 进入commitNowAllowingStateLoss这个方法看看怎么写的
我们看注释只能知其表,想知其理就需要看FragmentTransaction的实现类BackStackRecord

 @Override
    public int commit() {
        return commitInternal(false);
    }

    @Override
    public int commitAllowingStateLoss() {
        return commitInternal(true);
    }

    @Override
    public void commitNow() {
        disallowAddToBackStack();
        mManager.execSingleAction(this, false);
    }

    @Override
    public void commitNowAllowingStateLoss() {
        disallowAddToBackStack();
        mManager.execSingleAction(this, true);
    }

聪明的你已经看出来了 是否加入BackStack取决于disallowAddToBackStack();方法:

 @Override
    public FragmentTransaction disallowAddToBackStack() {
        if (mAddToBackStack) {
            throw new IllegalStateException(
                    "This transaction is already being added to the back stack");
        }
        mAllowAddToBackStack = false;
        return this;
    }

看到了吗? 我的异常也是爆了这里有错误:disallowAddToBackStack(BackStackRecord.java:600) 和我的切入点1 吻合,只是这个异常写的让人无所适从。

    原文作者:埃赛尔
    原文地址: https://www.jianshu.com/p/03bc7d76a86a
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞