commit(), commitNow()和commitAllowingStateLoss()
关于FragmentTransaction的各种提交方法: commit()
,commitAllowingStateLoss()
,commitNow()
和commitNowAllowingStateLoss()
.
作者Bryan Herbst发了一个blog The many flavors of commit()讨论这几个方法的特点和用途.
下文是中文摘要.
FragmentTransaction的提交方法
support library的FragmentTransaction
现在提供了四种不同的方法来commit一个transaction:
commit()
commitAllowingStateLoss()
commitNow()
commitNowAllowingStateLoss()
这篇文章分析了这四个方法的不同.
commit() vs commitAllowingStateLoss()
用commit()
提交有时候会遇到IllegalStateException
, 说你在onSaveInstanceState()
之后提交, 这里有另一个文章很好地分析了这个问题:Fragment Transactions & Activity State Loss
commit()
和commitAllowingStateLoss()
在实现上唯一的不同就是当你调用commit()
的时候, FragmentManger会检查是否已经存储了它自己的状态, 如果已经存了, 就抛出IllegalStateException
.
那么如果你调用的是commitAllowingStateLoss()
, 并且是在onSaveInstanceState()
之后, 你可能会丢失掉什么状态呢?
答案是你可能会丢掉FragmentManager的状态, 即save之后任何被添加或被移除的Fragments.
举例说明:
1.在Activity里显示一个FragmentA;
2.然后Activity被后台, onStop()
和onSaveInstanceState()
被调用;
3.在某个事件触发下, 你用FragmentB replace FragmentA , 使用的是 commitAllowingStateLoss()
.
这时候, 用户再返回应用, 可能会有两种情况发生:
1.如果系统杀死了你的activity, 你的activity将会重建, 使用了上述步骤2保存的状态, 所以A会显示, B不会显示;
2.如果系统没有杀死你的activity, 它会被提到前台, FragmentB就会显示出来, 到下次Activity stop的时候, 这个包含了B的状态就会被存下来.
(上述测试可以利用开发者选项中的”Don’t Keep Activities”选项).
那么你要选择哪一种呢? 这就取决于你提交的是什么, 还有你是否能接受丢失.
commit(), commitNow() 和 executePendingTransactions()
使用commit()
的时候, 一旦调用, 这个commit并不是立即执行的, 它会被发送到主线程的任务队列当中去, 当主线程准备好执行它的时候执行.
popBackStack()
的工作也是这样, 发送到主线程任务队列中去. 也即说它们都是异步的.
但是有时候你希望你的操作是立即执行的, 之前的开发者会在commit()
调用之后加上 executePendingTransactions()
来保证立即执行, 即变异步为同步.
support library从v24.0.0开始提供了 commitNow()
方法, 之前用executePendingTransactions()
会将所有pending在队列中还有你新提交的transactions都执行了, 而commitNow()
将只会执行你当前要提交的transaction. 所以commitNow()
避免你会不小心执行了那些你可能并不想执行的transactions.
但是你不能对要加在back stack中的transaction使用commitNow()
, 即addToBackStack()
和commitNow()
不能同时使用.
为什么呢?
想想一下, 如果你有一个提交使用了commit()
, 紧接着又有另一个提交使用了commitNow()
, 两个都想加入back stack, 那back stack会变成什么样呢? 到底是哪个transaction在上, 哪个在下? 答案将是一种不确定的状态, 因为系统并没有提供任何保证来确保顺序, 所以系统决定干脆不支持这个操作.
前面提过popBackStack()
是异步的, 所以它同样也有一个同步的兄弟popBackStackImmediate()
.
所以实际应用的时候怎么选择呢?
- 如果你需要同步的操作, 并且你不需要加到back stack里, 使用
commitNow()
.
support library在FragmentPagerAdapter里就使用了commitNow()来保证在更新结束的时候, 正确的页面被加上或移除. - 如果你操作很多transactions, 并且不需要同步, 或者你需要把transactions加在back stack里, 那就使用
commit()
. - 如果你希望在某一个指定的点, 确保所有的transactions都被执行, 那么使用
executePendingTransactions()
.
Reference
这是Android Weekly #220的一篇文章, 我在做这期笔记的时候觉得这个写得很好, 所以决定单独拿出来说一说. 这期整体的笔记稍后推出, 敬请期待哇.
原文The many flavors of commit()
commit(), commitNow()和commitAllowingStateLoss()的更多相关文章
- 【从零开始撸一个App】Fragment和导航中的使用
Fragment简介 Fragment自从Android 3.0引入开始,它所承担的角色就是显而易见的.它之于Activity就如html片段之于页面,好处无需赘述. Fragment的生命周期和Ac ...
- FragmentTransaction的commit和commitAllowingStateLoss的差别
1.什么是FragmentTransaction? 使用Fragment时.能够通过用户交互来运行一些动作.比方添加.移除.替换等. 全部这些改变构成一个集合,这个集合被叫做一个transaction ...
- Android Weekly Notes Issue #220
Android Weekly Issue #220 August 28th, 2016 Android Weekly Issue #220 ARTICLES & TUTORIALS Manag ...
- 选择正确的 Fragment#commitXXX() 函数
转自: http://www.tuicool.com/articles/q6R7nii 最新版本(v24.0.0)的 Support v4 库中的 FragmentTransaction 添加了 co ...
- Fragment Transactions和Activity状态丢失
本文由 伯乐在线 - 独孤昊天 翻译.未经许可,禁止转载!英文出处:androiddesignpatterns.欢迎加入翻译组. 下面的堆栈跟踪和异常代码,自从Honeycomb的初始发行版本就一直使 ...
- 行政区划sql数据脚本
行政区划sql数据脚本 IF (EXISTS(SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TB_Province]') ...
- Fragment回退栈&commit()和commitAllowingStateLoss()
Activity切换时是通过栈的形式,不断压栈出栈,在Fragment的时候,如果你不是手动开启回退栈,它是直接销毁再重建,但如果将Fragment任务添加到回退栈,情况就会不一样了,它就有了类似Ac ...
- 从源码看commit和commitAllowingStateLoss方法区别
Fragment介绍 在很久以前,也就是我刚开始写Android时(大约在2012年的冬天--),那时候如果要实现像下面微信一样的Tab切换页面,需要继承TabActivity,然后使用TabHost ...
- Android_Fragment栈操作 commit()问题分析
栈操作时遇到一个问题 getFragmentManager().beginTransaction() .replace(R.id.fl_container,bFragment) .addToBackS ...
随机推荐
- 第14章 Linux启动管理(1)_系统运行级别
1. CentOS 6.x 启动管理 (1)系统运行级别 ①运行级别 运行级别 含义 0 关机 1 单用户模式,可以想象为Windows的安全模式,主要用于系统修复.(但不是Linux的安全模式) 2 ...
- ASP.NET Core "完整发布,自带运行时" 到jexus
一.阅读前须知 1.使用 jexus整合asp.net core的优点: 1)支持多站点,同一端口可以同时支持任何多的asp.net core应用程序: 2)应用程序启动.停 ...
- Linux 系统中发博客必备的五大图片处理神器
发博客时,总免不了要用图片说话.经过长时间的磨合,在 Linux 桌面系统下有几款图片处理软件我已经用得比较顺手了.这几款软件在 Linux 世界使用广泛,各个 Linux 发行版的软件仓库中都有自带 ...
- MapReduce剖析笔记之六:TaskTracker初始化任务并启动JVM过程
在上面一节我们分析了JobTracker调用JobQueueTaskScheduler进行任务分配,JobQueueTaskScheduler又调用JobInProgress按照一定顺序查找任务的流程 ...
- [异常解决] JLINK 与STM32的SWD连接接线方式
如果我们的板子上只留了4个接口:V3.3,SWDIO,SWDCLK,GND.那么和JTAG的连接关系参见下图: 注意缺口方向.然后GND可以接左边任何一个pin(除了最底下这个PIN). FROM: ...
- JavaScript随笔3
1.获取非行间css if(oDiv.currentStyle){ alert(oDiv.currentStyle.width); }else{ alert(oDiv.getComputedStyle ...
- Java学习笔记(05)
目录: static的用法 主函数的定义 增强for的循环 单例设计模式 封装 一.Static的用法 1.对象的内存分析 对象的引用变量是存在于栈区,而在堆区开辟了一块内存空间,调用对象给成员变量赋 ...
- 使用WordPress搭建自己的博客
突然间发现自己在阿里上有一个免费的虚拟云空间,好像是什么时候阿里云搞活动赠送的.看了看还有不少时间,就决定自己搭建一个博客系统.说到搭建自己的博客,第一时间就想到WordPress,这个用起来应该是最 ...
- Oracle 11g静默安装软件+手工创建数据库
由于是二次跳转+远程操作,无法使用图形界面,不能直接图形界面安装.采用静默安装软件+手工创建数据库的方式完成需求. 静默模式安装Oracle软件,配置监听程序 手工建库 检查各组件是否符合要求 1. ...
- RAC 主库配置单实例ADG
1.主库准备工作 2.物理备库准备工作 3.创建物理备库 写在前面: 最终实现环境:11.2.0.4版本 2节点RAC + 1节点DG 本文旨在弄清楚整个搭建过程中涉及到的基础概念: 本文安装maxi ...