Android-为何以及如何保存Fragment实例
在安卓开发中,由于旋转设备会造成配置改变进而导致Activity实例被摧毁(当然也包括Activity托管的Fragment)。Activity或Fragment实例被摧毁自然也就让Model被摧毁,数据也就没有了。这是我们不想看到的。因此有了重写Activity或者Fragment的onSavedInstanceState(Bundle)方法来保存Model。
通过上述的这种方法的确可以解决一部分数据被摧毁的问题,但是有些数据我们需要一直保持,而非摧毁->重建。比如听音乐听得好好的,我旋转设备,程序员通过onSavedInstanceState(Bundle)方法把音乐保存了,然后onCreate(Bundle)再来将刚刚摧毁的音乐放出来,这可以么?当然不行,你说你吃着火锅唱着歌,就旋转个屏幕,音乐突然就没了,然后嘿又好了,你不骂这个app开发者傻逼我都看不下去!因此有了一个新需求,在设备旋转等配置改变的情况下我们要让model一直在,而不是摧毁->重建。这个想想好像无从下手,其实不难。我们可以跳出保存Model的思路,而是直接让存放Model的Fragment就不会死,那不就行了。
讲完了为何,再来说如何保存Fragment实例。
我们只需要重写Fragment.onCreate()方法,加上setRetainInstance(true)就行了

知其然须知其所以然,我们应该对系统是如何保存了fragment实例的工作原理也要了解。
如果不写setRetainInstance(true)这句话会发生什么呢?

如上图所示,由于旋转完屏幕,设置被改变,FragmentManager会首先销毁队列中fragment的视图,为什么要销毁它们的原因也很简单,新的配置可能对应新的资源,当有更适合的新资源匹配时,需要更换成新视图。然后FragmentManager会依次检查fragment实例的retainInstance值,如果为false立即销毁fragment实例。然后众所周知,会有一个新的Activity创建一个新的FragmentManager来创建新的Fragment实例及其视图。
但是如果fragment实例的retainInstance值为true,就不会被销毁。当新的Activity创建新的FragmentManager时,会找到这个被保存的fragment实例,并重新创建它的视图。

这个"不会死"的fragment,在activity被摧毁时处于被保留状态,此时没有任何activity托管它(因为托管它的activity被摧毁了)。
再来看看fragment的生命周期,加深理解。

从上面大段的讲述,我们可以总结出fragment需要有如下两个条件才能进入被托管状态。
1.它的retainInstance值为true
2.托管它的activity正在被摧毁
等到activity重建,fragment被纳入麾下,被保留状态也就结束了。
再来比较一下onSaveInstance方法和保留fragment实例方法
先看图:

由图可得出,在进程关闭时(通常可能发生在用户暂时离开当前应用以及系统需要回收内存从而销毁了activity以及被保留的fragment实例时),fragment依然会被摧毁。
因此在需要将数据保存时间和activity记录一样长时,并且无需连贯保持(至少表面看不出来是断掉的)的情况时,最好采用onSaveInstance方法。
太阳照常升起,人生寂寞如雪。
Android-为何以及如何保存Fragment实例的更多相关文章
- Android为TV端助力 fragment 的用法以及与activity的交互和保存数据的方法,包括屏幕切换(转载)!
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37992017 1.管理Fragment回退栈 类似与Android系统为Acti ...
- Android开发之漫漫长途 Fragment番外篇——TabLayout+ViewPager+Fragment
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- Android面试收集录4 Fragment详解
1.什么是Fragment? 你可以简单的理解为,Fragment是显示在Activity中的Activity. 它可以显示在Activity中,然后它也可以显示出一些内容. 因为它拥有自己的生命周期 ...
- Fragment-如何监听fragment中的回退事件与怎样保存fragment状态
一.如何监听Fragment中的回退事件 1.问题阐述 在Activity中监听回退事件是件非常容易的事,因为直接重写onBackPressed()函数就好了,但当大家想要监听Fragment中的回退 ...
- Android解惑 - 为什么要用Fragment.setArguments(Bundle bundle)来传递参数(转)
Fragment在Android3.0开始提供,并且在兼容包中也提供了Fragment特性的支持.Fragment的推出让我们编写和管理用户界面更快捷更方便了. 但当我们实例化自定义Fragmen ...
- 【Android 应用程序开发】 Fragment 详细说明
笔者 : 汉书亮 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/38064191 本博客代码地址 : -- 单一 Fragmen ...
- Android 两步搞定Fragment的返回键
Fragment可以说是在Android开发必需要使用到技术,项目中的界面基本上都是使用Fragment来实现,而Activity只是作为Fragment的载体,但有些特殊情况下Fragment也不得 ...
- android activity状态的保存
今天接到一个电面,途中面试官问到一个问题,如果一个activity在后台的时候,因为内存不足可能被杀死,在这之前如果想保存其中的状态数据,比如说客户填的一些信息之类的,该在哪个方法中进行. onSav ...
- Android应用底部导航栏(选项卡)实例
现在很多android的应用都采用底部导航栏的功能,这样可以使得用户在使用过程中随意切换不同的页面,现在我采用TabHost组件来自定义一个底部的导航栏的功能. 我们先看下该demo实例的框架图: 其 ...
随机推荐
- 返回 m 到 n 的随机整数
返回 m 到 n 的随机整数 <script type="text/javascript"> function randomNumber(m,n){ return Ma ...
- 利用js得到某个范围内的整数随机数
Math.random()方法可以返回(0,1)之间的随机数,不包括0和1. 套用公式:Math.floor(Math.random()*可能的值的总数+第一个可能的值) 如得到(3,9]之间的随机数 ...
- JavaScript:Object.prototype.toString方法的原理
在JavaScript中,想要判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法. var arr = []; console.log(Obje ...
- C++中复制构造函数与重载赋值操作符
我们都知道,在C++中建立一个类,这个类中肯定会包括构造函数.析构函数.复制构造函数和重载赋值操作:即使在你没有明确定义的情况下,编译器也会给你生成这样的四个函数.例如以下类: class CTe ...
- Matlab与外部接口:MAT文件基础
MAT 文件MAT文件是MATLAB使用的一种特有的二进制数据文件.MAT文件可以包含一个或者多个MATLAB 变量.MATLAB通常采用MAT文件把工作空间的变量存储在磁盘里,在MAT文件中不仅保存 ...
- 使用 Nuget打包类库
使用 Nuget打包类库 NuGet是个开源项目,项目包括 NuGet VS插件/NuGet Explorer/NuGetServer/NuGet命令行等项目,.NET Core项目完全使用Nuget ...
- Swift—Core Foundation框架-备
Core Foundation框架是苹果公司提供一套概念来源于Foundation框架,编程接口面向C语言风格的API.虽然在Swift中调用这种C语言风格的API比较麻烦,但是在OS X和iOS开发 ...
- 体验Lua
想用之和NGINX结合,终结公司混乱的NGINX配置 玩起来先,感觉很精简,很实用哟. print("hello world") a={,} b=a print(a==b,a~=b ...
- Check if a string is NULL or EMPTY using PowerShell
http://techibee.com/powershell/check-if-a-string-is-null-or-empty-using-powershell/1889 Check if a s ...
- js 中比较 undefined
// x has not been declared before if (typeof x === 'undefined') { // evaluates to true without error ...