FragmentTransaction的commit和commitAllowingStateLoss的差别

1、什么是FragmentTransaction?

使用Fragment时。能够通过用户交互来运行一些动作。比方添加、移除、替换等。

全部这些改变构成一个集合,这个集合被叫做一个transaction。

能够调用FragmentTransaction中的方法来处理这个transaction,而且能够将transaction存进由activity管理的back stack中,这样用户就能够进行fragment变化的回退操作。

能够这样得到FragmentTransaction类的实例:

FragmentManager  mFragmentManager = getSupportFragmentManager();
FragmentTransaction  mFragmentTransaction = mFragmentManager.beginTransaction();

2、commit和executePendingTransactions的差别

用add(), remove(), replace()方法,把全部须要的变化加进去,然后调用commit()方法。将这些变化应用。

在commit()方法之前,你能够调用addToBackStack(),把这个transaction增加back stack中去,这个back stack是由activity管理的。当用户按返回键时,就会回到上一个fragment的状态。

你仅仅能在activity存储它的状态(当用户要离开activity时)之前调用commit()。假设在存储状态之后调用commit()。将会抛出一个异常。

这是由于当activity再次被恢复时commit之后的状态将丢失。假设丢失也没关系。那么使用commitAllowingStateLoss()方法。

3、问什么在存储状态之后调用commit会报异常?

我们查看Android源代码发现FragmentManager和FragmentTransaction是一个虚类

那他们在activity中的实例化代码是怎样处理的呢?

首先是getSupportFragmentManager的方法

/**
     * Return the FragmentManager for interacting with fragments associated
     * with this activity.
     */
    public FragmentManager getSupportFragmentManager() {
        return mFragments;
    }

查找到mFragments。

final FragmentManagerImpl mFragments = new FragmentManagerImpl();

我们发现FragmentManagerImpl是继承于FragmentManager的一个实体类

/**
 * Container for fragments associated with an activity.
 */
final class FragmentManagerImpl extends FragmentManager {

    ........

    @Override
    public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }

    ........

    }

为了简便我们删除了一些不要的代码仅仅留下关键的方法。

通过这段代码。我们能够查看到beginTransaction方法实际返回的是一个继承于FragmentTransaction的BackStackRecord类

我们来查看BackStackRecord的代码,查看他的使用方法

/**
 * @hide Entry of an operation on the fragment back stack.
 */
final class BackStackRecord extends FragmentTransaction implements
        FragmentManager.BackStackEntry, Runnable {

	..........
	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);
        mCommitted = true;
        if (mAddToBackStack) {
            mIndex = mManager.allocBackStackIndex(this);
        } else {
            mIndex = -1;
        }
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }
	..........

}

绕了大半天,最终找到commit方法和commitAllowingStateLoss方法,他们都同一时候调用了commitInternal方法,仅仅是传的參数略有不同。一个是true。一个是false。我们发如今运行这种方法之前会首先对mCommitted进行推断,依据代码语义我们能够知道mCommitted就是是否已经commit的意思

最后,commitInternal调用了mManager.enqueueAction的方法。

让我们回到FragmentManager,看这种方法是怎样操作的。

我们找到这种方法。

/**
 * @hide Entry of an operation on the fragment back stack.
 */
final class BackStackRecord extends FragmentTransaction implements
        FragmentManager.BackStackEntry, Runnable {

	..........
	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);
        mCommitted = true;
        if (mAddToBackStack) {
            mIndex = mManager.allocBackStackIndex(this);
        } else {
            mIndex = -1;
        }
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }
	..........

}

经分析后,我们能够发现。此方法在对 commit和commitAllowingStateLoss的传參进行推断后。将任务扔进activity的线程队列中。那这个两个方法差别就在传參推断后的处理方法checkStateLoss,那接下来,让我们查看一下checkStateLoss方法。看对參数进行推断后,做了什么样的处理。

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);
        }
    }

ok,到这里。真相总算大明。当使用commit方法时,系统将进行状态推断,假设状态(mStateSaved)已经保存,将发生"Can not perform this action after onSaveInstanceState"错误。

假设mNoTransactionsBecause已经存在,将发生"Can not perform this action inside of " + mNoTransactionsBecause错误。

时间: 2024-10-12 12:46:25

FragmentTransaction的commit和commitAllowingStateLoss的差别的相关文章

FragmentTransaction的commit和commitAllowingStateLoss的区别

1.什么是FragmentTransaction? 使用Fragment时,可以通过用户交互来执行一些动作,比如增加.移除.替换等. 所有这些改变构成一个集合,这个集合被叫做一个transaction. 可以调用FragmentTransaction中的方法来处理这个transaction,并且可以将transaction存进由activity管理的back stack中,这样用户就可以进行fragment变化的回退操作. 可以这样得到FragmentTransaction类的实例: Fragm

FragmentTransaction的commit的异步操作

FragmentTransaction是异步的,commit()仅是相当于把操作加入到FragmentManager的队列,然后FragmentManager会在某一个时刻来执行,并不是立即执行.所以,真正开始执行commit()时,如果Activity的生命周期发生了变化,比如走到了onPause,或者走到了onStop,或者onDestroy都走完了,那么就会报出IllegalStateException. 这个地方确实是很坑的,我在做一个功能,需要从FragmentA跳转到Fragment

android FragmentTransaction.replace的用法介绍

创建Fragment Fragment和Activity有很多相似之处,例如可以不带UI,但这样做对两者似乎都没什么意义.他们的创建方式也很相似,例如下面的代码: [html] view plaincopyprint? package test.fragments; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View;

Fragment Transactions和Activity状态丢失

本文由 伯乐在线 - 独孤昊天 翻译.未经许可,禁止转载!英文出处:androiddesignpatterns.欢迎加入翻译组. 下面的堆栈跟踪和异常代码,自从Honeycomb的初始发行版本就一直使得StackOverflow很迷惑. 1 2 3 4 5 java.lang.IllegalStateException:Can not perform this action after onSaveInstanceState     at android.support.v4.app.Fragm

Android实际开发中的bug总结与解决方法(一)

                                                                             Android实际开发中的bug总结与解决方法(一) Android开发中有很多bug,我们是完全可以在线下避免的,不要等到线上报的BUG的再去修复.下面是我在实际开发中遇到过的bug和解决方法. BUG 1: java.lang.RuntimeException: Unable to start activity ComponentInfo

放QQ菜单栏:消息,电话菜单

转载自:http://blog.csdn.net/johnnyz1234/article/details/45919907 在实际项目开发使用Fragment的时候,也碰到一些异常和存在的问题,下面做下简单的总结笔记,后面还会不定时补充更新. 1.关于Fragment的生命周期的几点认识 Fragment的完整生命周期开始于绑定到它的父Activity,结束于从父Activity上分离.通过分别调用onAttach和onDetach来表示这些事件. 在Fragment/Activity 被暂停之

Fragment提交transaction导致state loss异常

下面自从Honeycomb发布后,下面栈跟踪信息和异常信息已经困扰了StackOverFlow很久了. java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1341) at android.support.v4.a

ILJMALL project过程中遇到Fragment嵌套问题:IllegalArgumentException: Binary XML file line #23: Duplicate id

出现场景:当点击"分类"再返回"首页"时,发生error退出 BUG描述:Caused by: java.lang.IllegalArgumentException: Binary XML file line #23: Duplicate id 0x7f0d0054, tag null, or parent id 0xffffffff with another fragment for com.example.sxq123.iljmall.FragmentCatag

API翻译 --- Fragments

IN THIS DOCUMENT Design Philosophy 设计理念 Creating a Fragment 创建一个Fragment Adding a user interface  添加一个用户接口 Adding a fragment to an activity 给Activity添加一个Fragment Managing Fragments  管理Fragment Performing Fragment Transactions 执行Fragment事务 Communicati