选择正确的 Fragment#commitXXX() 函数

转自: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

commit() vs commitAllowingStateLoss()

大部分使用 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 的时候可能出现以下两种状态:

  1. 若是系统内存不足而且杀死了您的应用,当用户从新打开您的 应用的时候,系统将会恢复您的应用到上面第二步的状态,而 FragmentB 是不会显示的。
  2. 若是系统没有杀死您的应用,用户则能够看到 FragmentB。当 Activity 再次回到后台的时候(onStop), FragmentB 的状态才会被保存起来。

Github 上有个示例项目 演示该状况。在运行该示例的时候,若是打开开发者选项中的 “Don’t Keep Activities” 设置,则能够用来显示第一种状况,FragmentB 的状态彻底丢失了。 若是没有打开 “Don’t Keep Activities” 选项,则能够查看第二种状况。

这两个函数使用哪一个取决于您提交的 Fragment 和 该 Fragment 状态是否重要,若是状态丢失了也不要紧,则您可使用 commitAllowingStateLoss() 函数。

commit(), commitNow(), 和 executePendingTransactions()

其余版本的 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() 的状况是同样的。

最后来总结下该如何选择这些函数:

  • 若是你须要同步提交 Fragment 而且无需添加到 堆栈 中,则使用 commitNow()。 Support 库中在 FragmentPagerAdapter 中使用这个函数,来确保更新 Adapter 的时候 正确的页面被添加和删除了。通常来讲,只要不添加到堆栈中,均可以使用这个函数来提交。
  • 若是执行了屡次提交,而且不须要是同步的,或者把每次提交都添加到 堆栈 中,那么就使用 commit()。
  • 若是 您须要把屡次提交操做的同一个时间点一块儿执行,则使用 executePendingTransactions()
相关文章
相关标签/搜索