Android碎片事务提交transaction.commit()和transaction.commitnow()的区别以及源码完全解析

先普及一个知识

当你调用了碎片空的构造器的时候,你的碎片并不会执行生命周期的方法,如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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值