先普及一个知识
当你调用了碎片空的构造器的时候,你的碎片并不会执行生命周期的方法,如onCreateView()等
什么时候会执行生命周期呢?
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(mContainerId, mFragment);
transaction.commit();
当你把这个碎片add进fragmentmanager(碎片栈),或者replace(是remove和add的结合体)进去的时候,你才会进入碎片的生命周期。
既然commit就可以进入碎片的生命周期那commitNow又是做什么用的?
顾名思义,commitNow就是立刻提交事务,那也不难推断出commit其实提交后,并没有立刻执行你所期待的操作。
那么什么时候执行呢?他们的具体区别到底在哪呢?我用一个实例分析一下。
NavFragment navFragment = new NavFragment(); addFragment(R.id.fl_nav, navFragment); navFragment.setup();如果你的addFragment里的事务提交是commit方法,那么你的执行流程是这样的:虽然你addFragment方法里你commit了,但是commit是会被搁置的,当你活动中接下来的所有初始化代码执行完以后,才会去真正执行把碎片add进fragmentmanager的栈中,并且执行碎片一系列的生命周期操作。
如果你的addFragment里的事务提交是commitNow方法,那你的执行流程是这样的:先把碎片那一系列的生命周期操作执行了,让你的碎片真正被“激活”了,才会按顺序执行你activity中的余下代码。
我们先追溯一下commit的源码,在FragmentTransaction中
/** * Schedules a commit of this transaction. The commit does * not happen immediately; it will be scheduled as work on the main thread * to be done the next time that thread is ready. * * <p class="note">A transaction can only be committed with this method * prior to its containing activity saving its state. If the commit is * attempted after that point, an exception will be thrown. This is * because the state after the commit can be lost if the activity needs to * be restored from its state. See { @link #commitAllowingStateLoss()} for * situations where it may be okay to lose the commit.</p> * * @return Returns the identifier of this transaction's back stack entry, * if { @link #addToBackStack(String)} had been called. Otherwise, returns * a negative number. */ public abstract int commit();
你会惊讶的发现commit是一个抽象方法,并且附上了一段密密麻麻的注释。先不急找到这个方法的实现类,我们采用谷歌翻译对注释进行翻译抽取有用的信息。
计划提交此事务。提交确实不是马上发生;它将被安排在主线程上工作,待下次线程准备完成。
后面是讲到如果是因为你活动需要执行了这个commit,那么你在排队的过程中信息有可能会丢失,但是可以从存储的状态中恢复(没啥用)
经过寻找,BackStackRecord是FragmenTransaction的实现类。我们定位commit的方法
@Override public int commit() { return commitInternal(false); }
继续寻找commitInternal方法
int commitInternal(boolean allowStateLoss) { if (mCommitted) throw new IllegalStateException("commit already called"); if (FragmentManagerImpl.DEBUG) { Log.v(TAG, "Commit: " + this); LogWriter l