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错误。

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

  1. Fragment回退栈&commit()和commitAllowingStateLoss()

    Activity切换时是通过栈的形式,不断压栈出栈,在Fragment的时候,如果你不是手动开启回退栈,它是直接销毁再重建,但如果将Fragment任务添加到回退栈,情况就会不一样了,它就有了类似Ac ...

  2. FragmentTransaction的commit的异步操作

    FragmentTransaction是异步的,commit()仅是相当于把操作加入到FragmentManager的队列,然后FragmentManager会在某一个时刻来执行,并不是立即执行.所以 ...

  3. 从源码看commit和commitAllowingStateLoss方法区别

    Fragment介绍 在很久以前,也就是我刚开始写Android时(大约在2012年的冬天--),那时候如果要实现像下面微信一样的Tab切换页面,需要继承TabActivity,然后使用TabHost ...

  4. commit(), commitNow()和commitAllowingStateLoss()

    关于FragmentTransaction的各种提交方法: commit(),commitAllowingStateLoss(),commitNow()和commitNowAllowingStateL ...

  5. 怎么通过activity里面的一个按钮跳转到另一个fragment(android FragmentTransaction.replace的用法介绍)

    即:android FragmentTransaction.replace的用法介绍 Fragment的生命周期和它的宿主Activity密切相关,几乎和宿主Activity的生命周期一致,他们之间最 ...

  6. Fragment Transactions和Activity状态丢失

    本文由 伯乐在线 - 独孤昊天 翻译.未经许可,禁止转载!英文出处:androiddesignpatterns.欢迎加入翻译组. 下面的堆栈跟踪和异常代码,自从Honeycomb的初始发行版本就一直使 ...

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

    出现场景:当点击"分类"再返回"首页"时,发生error退出   BUG描述:Caused by: java.lang.IllegalArgumentExcep ...

  8. Android Weekly Notes Issue #220

    Android Weekly Issue #220 August 28th, 2016 Android Weekly Issue #220 ARTICLES & TUTORIALS Manag ...

  9. Fragment提交transaction导致state loss异常

    下面自从Honeycomb发布后,下面栈跟踪信息和异常信息已经困扰了StackOverFlow很久了. java.lang.IllegalStateException: Can not perform ...

随机推荐

  1. SQLite -- 嵌入式关系型数据库

    SQLite -- 嵌入式关系型数据库 1.SQLite的数据类型:Typelessness(无类型) 1,能够保存不论什么类型的数据到表的随意列中 2.支持常见的类型如: NULL, VARCHAR ...

  2. ModelForm views.py

    from django.shortcuts import render from django import forms from django.forms import fields from ap ...

  3. List methods

    Python provides methods that operate on lists. For example, append adds a new element to the end of ...

  4. Storm框架基础(一)

    * Storm框架基础(一) Storm简述 如果你了解过SparkStreaming,那么Storm就可以类比着入门,在此我们可以先做一个简单的比较:  在SparkStreaming中: 我们曾尝 ...

  5. python 3.x 学习笔记4(函数)

    1.编程方式分:面向对象.面向过程.函数式编程 2.区分面向对象---->类---->class面向过程---->过程---->def函数式编程---->函数----&g ...

  6. PostgreSQL环境中查看SQL执行计划示例

    explain   analyze ,format,buffers, format :TEXT, XML, JSON, or YAML. EXPLAIN (ANALYZE,buffers,format ...

  7. css hover图片hover效果兼容ie8

    例子: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...

  8. WLAN STA/AP 并发

    WLAN STA/AP 并发 Android 9 引入了可让设备同时在 STA 和 AP 模式下运行的功能.对于支持双频并发 (DBS) 的设备,此功能让一些新功能得以实现,例如在用户想要启用热点 ( ...

  9. 比起 Windows,怎样解读 Linux 的文件系统与目录结构?

    Linux 和 Windows 的文件系统有些不同,在学习使用 Linux 之前,若能够了解这些不同,会有助于后续学习. 本文先对 Windows 和 Linux 上面文件系统原理.组织概念进行区分, ...

  10. 了解Linux的基础知识和一般概念

    1.GNU和GPL    GNU计划(又称革奴计划),是由Richard Stallman(理查德·斯托曼)在1983年9月27日公开发起的自由软件集体协作计划.它的目标是创建一套完全自由的操作系统. ...