转自:html
http://www.tuicool.com/articles/q6R7niijava
最新版本(v24.0.0)的 Support v4 库中的 FragmentTransaction 添加了 commitNow() 和 commitNowAllowingStateLoss () 两个函数,这样 提交一个 Fragment 就有以下4个函数能够选择:android
– commit()git
– commitAllowingStateLoss()github
– commitNow()app
– commitNowAllowingStateLoss()函数
另外,在使用 Fragment 的过程当中,可能您已经使用过了 executePendingTransactions() 这个函数了。ui
下面来深刻分析下每一个函数是干啥用的,你应该使用哪一个函数。this
大部分使用 Fragment 的开发者可能都遇到过以下的异常:线程
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
Alex Lockwood 写过一篇文章来详细解释为什么会出现该异常。可是开发者更多的是想知道他们的应用出现了该问题意味着什么?
commit() 和 commitAllowingStateLoss() 的实现几乎是同样的。惟一的区别就是在调用 commit() 的时候 FragmentManager 会检查是否已经保存了其状态,若是状态已经保存了,则就抛出 IllegalStateException 异常。
那么,在 onSaveInstanceState() 函数执行之后,您调用 commitAllowingStateLoss() 会丢失那些状态呢? 答案就是你可能丢失 FragmentManager 的状态,这里面包含在 onSaveInstanceState() 执行以后添加和删除的 Fragment。
例如:
1. 当前您的 Activity 在显示 FragmentA
2. 您的 Activity 被切换到后台了((onStop() 和 onSaveInstanceState() 函数被调用了)
3. 这个时候您的 Activity 的逻辑发生了一些变化,您使用 FragmentB 替换了 FragmentA 并调用了 commitAllowingStateLoss() 函数来提交这个变化。
这个时候,当用户再次切回您的 Activity 的时候可能出现以下两种状态:
Github 上有个示例项目 演示该状况。在运行该示例的时候,若是打开开发者选项中的 “Don’t Keep Activities” 设置,则能够用来显示第一种状况,FragmentB 的状态彻底丢失了。 若是没有打开 “Don’t Keep Activities” 选项,则能够查看第二种状况。
这两个函数使用哪一个取决于您提交的 Fragment 和 该 Fragment 状态是否重要,若是状态丢失了也不要紧,则您可使用 commitAllowingStateLoss() 函数。
其余版本的 commit() 指定了提交发生的时机。 commit() 的文档有以下说明:
安排一个针对该事务的提交。提交并无马上发生,会安排到在主线程下次准备好的时候来执行。 (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.)
上面文档说明的意思是,你能够同时执行屡次提交,这些提交都没有马上执行,知道下次主线程准备好了才一块儿执行这些提交的 Fragment。这些针对 Fragment 的提交操做包含 添加、删除、替换以及经过函数 popBackStack() 来返回前一个 Fragment。
有时候,您须要针对 Fragment 的操做马上执行。以前都是经过在调用函数 commit() 后调用 executePendingTransactions() 来实现的。
在 24.0.0 版本的 Support 库中添加了 commitNow() 函数来更好的支持这种操做。commitNow() 只同步的执行当前的提交操做,而 executePendingTransactions() 则会执行全部等得执行的操做。 commitNow() 能够避免您执行以前提交的可是无需马上执行的操做。
commitNow() 有个限制,没法把当前提交的 Fragment 添加到堆栈(back stack)中。假设有以下的状况:
经过 commit() 函数把 Fragment A 添加到堆栈中,而后马上使用 commitNow() 把另一个 Fragment B 添加到堆栈中,这样当前的堆栈应该是何种状态? 是 Fragment A 在前面仍是 Fragment B 在前面呢?
popBackStack() 和 popBackStackImmediate() 与 commit() 和 commitNow() 的状况是同样的。
最后来总结下该如何选择这些函数: