美文网首页Android进阶+实战技术Android 干货
Android中Fragment数据保存和恢复

Android中Fragment数据保存和恢复

作者: MeloDev | 来源:发表于2016-05-16 23:25 被阅读8096次

    Android中Fragment数据保存和恢复

    找到一个更好解释更清楚的方案:
    https://segmentfault.com/a/1190000006691830

    不要往下看了,过时了~

    写在前面:

    上周我们总结了Activity中数据的保存和恢复,我们花两分钟来回顾一下:

    Android中Activity数据的保存和恢复

    一句话总结:

    • 临时数据
      对于临时数据,我们使用onSaveInstanceState方法进行保存,并且在onCreate方法中恢复。

    • 永久数据
      对于持久性数据,我们要在onPause方法中进行存储,但是要注意,onPause方法中不能进行大量操作,会影响其他Activity进入任务栈栈顶。

    ps:在Activity中弹出一个当前Activity的Dialog并不会有任何生命周期方法调用(以前我曾以为会调用onPause方法)。因为Dialog作为一个View本身就是属于当前Activity的,Activity并没有失去焦点

    ok,完成了回顾,下面来开始本篇博客:

    Fragment在我们的项目中真的太实用和常见了,它的使用频率和数量甚至超过了Activity,所以本文目的是探究Fragment的数据保存和恢复。

    在开始讲解之前,你应该对Fragment的生命周期方法有一定了解,推荐给大家一篇博客,我认为不错:

    Fragment生命周期方法详解

    准备工作做了这么多,下面我们正式开始吧!

    测试App截图

    本文直接选用了《第一行代码》中Fragment模块的讲解例子,点击下面的按钮分别跳转这四个Fragment。为了方便观察,我重写了Fragment所有生命周期方法onSaveInstanceState方法,并打印了Log。

    我们目的是探究Fragment数据的保存和恢复,在这里我把它分为两大类的情况:

    1. 单个Fragment遭遇一些突发情况

    2. Fragment之间相互的切换或覆盖

    在此之前,先引入一个返回栈的概念。
    我想你应该知道返回栈是什么,并且你以前接触的应该是保存Activity的返回栈,类比Activity,Fragment返回栈其实是保存Fragment的栈结构。区别在于:Fragment的返回栈由Activity管理;而Activity的返回栈由系统管理。

    在未修改之前,本文添加并切换Fragment的方式都是在返回栈中仅有一个 fragment:

    添加切换fragment

    不要心急,过一会再说怎么去在返回栈中压入多个fragment,我们先来处理只有一个的情况

    1. 单个Fragment遭遇突发情况

      仍然是用以下突发情况进行测试:

      • 点击back键

      • 点击锁屏键

      • 点击home键

      • 其他APP进入前台

      • 启动了另一个Activity

      • 屏幕方向旋转

      • APP被Kill

      不过与上篇博客不同的是,我们在清单文件中,给Activity做了如下配置:


      配置configChange

      这么做的目的是当屏幕方向发生改变的时候,fragment所依附的Activity并不会重新销毁再创建,让情况相对简单一点

      测试结果:

      当一个fragment孤零零地呆在返回栈时,它所处的情况与Activity如出一辙。类比Activity对数据的保存和恢复,我们可以对此得出结论:

      • 临时数据 对于临时数据,我们使用onSaveInstanceState方法进行保存,并且在onCreateView方法中恢复(请注意是onCreateView)。

      • 永久数据 对于持久性数据,我们要在onPause方法中进行存储。

    2. Fragment之间的相互切换或覆盖
      当返回栈中保证只有一个Fragment,相互切换时,生命周期方法的调用是怎样的呢?例如本例中,从fragment03切换到fragment04:

    fragment03切换fragment04

      可以看到,上述的这种情况,两个fragment从创建到销毁,经历了所有的生命周期方法。
      如果返回栈中fragment的数量为多个呢?首先在切换时,加上以下代码,保证将fragment放入返回栈中:

    addToBackStack

      使用addToBackStack方法,就能将fragment放入相应的返回栈中去了,从表象上来看区别在于进入其他fragment时,点击back键时,可以返回上一个fragment。这时候切换时,生命周期方法就是如何调用的呢?

    返回栈有多个fragment切换

    对比这两张生命周期方法的图,能得出两个结论。
      1.无论任务栈中fragment数量为多少,onSaveInstanceState方法都没有调用
      2.当fragment任务栈中有多个fragment时,进入下一个fragment时,并不会销毁fragment实例,而是仅仅销毁视图,最终调用的方法为onDestoryView。
      所以此时我们要去保存临时数据,并不能仅保存在onSaveInstanceState中(因为它可能不会调用),还应该在onDestoryView方法中进行保存临时数据的操作,源码如下:

    代码截图

    因为没有了系统提供的bundle参数,我们选择把数据保存在Arguments中,代码就不带着大家一步一步的看了,因为逻辑并不复杂,挺好理解的。通过这种方式,我们就挺容易的将临时数据和fragment的一些状态保存进bundle中并在需要时恢复了。

    不知不觉本篇文章就要结束了,感兴趣的可以尝试当调用ft.add()方式去添加fragment时,生命周期方法又是怎样调用的呢?

    结束之前我们来一句话总结下本文:
    Fragment对临时数据的保存,仅仅依靠onSaveInstanceState方法是不行的,还需要在onDestoryView中进行相应操作,具体参考上面的代码。

    Fragment中对于一些持久性的数据,仍应在onPause中保存。

    相关文章

      网友评论

      • fumier:博主,Fragment之间的相互切换或覆盖,当返回栈中保证只有一个Fragment,相互切换时。。这个例子,是返回栈没有fragment的情况吧。可以通过以下代码监听返回栈的fragment的个数。
        getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
        Log.d("backstack", getSupportFragmentManager().getBackStackEntryCount() + "");
        }
        });
        MeloDev:@fumier 感谢补充哇,啊哈哈
      • 5e02dfbe21ba:博主,我这边想请教个问题,我看这里关键恢复是利用的getArgument(),但是如果开始跳转的frament可能不需要携带参数过来,你这边不会出现报空指针的问题吗?
        MeloDev:@脱氧核糖核苷酸 是这样的,在相互切换之前我给fragment人为的设置setArguments,保正它不为空就行了
        5e02dfbe21ba:@MeloDev 博主,如果做了判空,但是getArgument()为空值,那还能通过什么做fragment的数组恢复呢
        MeloDev:@脱氧核糖核苷酸 确实应该加一下非空判断
      • b7e9763ffd86:mark, 有所收获,不过好像saveStateToArguments方法中不用空判断了,你的写法不太可能出现空在这里~
      • 520256894235:写的很好,思路清晰,Mark啦
        MeloDev:@戢鳞 喜欢就好~可以照着例子敲敲,印象会深刻一点

      本文标题:Android中Fragment数据保存和恢复

      本文链接:https://www.haomeiwen.com/subject/irnbrttx.html