设为首页 加入收藏

TOP

Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复(一)
2017-10-13 10:12:11 】 浏览:6470
Tags:Android Fragment 使用 Activity WebView 状态 保存 恢复

Android中的状态保存和恢复

Android中的状态保存和恢复, 包括Activity和Fragment以及其中View的状态处理.
Activity的状态除了其中的View和Fragment的状态之外, 还需要用户手动保存一些成员变量.
Fragment的状态有它自己的实例状态和其中的View状态, 因为其生命周期的灵活性和实际需要的不同, 情况会多一些.
根据源码, 列出了Fragment中实例状态和View状态保存和恢复的几个入口, 便于分析查看.
最后专门讲了WebView状态保存和恢复, 问题及处理.
还有一个工具类icepick的介绍.

Activity的状态保存和恢复

作为热身, 先来讲一下Activity的状态保存和恢复.

什么时候需要恢复Activity

关于Activity的销毁和重建, 之前有这么一篇博文: Activity的重新创建
总结来说, 就是Activity的销毁, 分为彻底销毁和留下数据的销毁两种.

彻底销毁是指用户主动去关闭或退出这个Activity. 此时是不需要状态恢复的, 因为下次回来又是重新创建全新的实例.
留下数据的销毁是指系统销毁了activity, 但是当用户返回来时, 会重新创建它, 让用户觉得它一直都在.

屏幕旋转重建可以归结为第二种情况, 打开Do not keep activities开关, 切换activities也是会出现第二种情况.
打开Do not keep activities开关就是为了模拟内存不足时的系统行为, 这里有一篇分析

如何恢复

实际上系统已经帮我们做好了View层面基本的恢复工作, 主要是依靠下面两个方法:

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // 在onStop()之前调用, 文档中说并不保证在onPause()的之前还是之后
        // 我的试验中一般是在onPause()之后
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        // 在onStart() 之后
    }

Bundle其中包含了activity中的view和fragment的各种信息, 所以调用基类的方法就可以完成基本的view层面的恢复工作.
注意这两个方法并不是activity的生命周期回调, 对于activity来说它们不是一定会发生的.
另外需要注意的是, View必须要有id才能被恢复.

举一个实例来说明:
Activity A start B, 那么A的onSaveInstanceState()会在onStop()之前调用, 以防A被系统销毁.
但是在B中按下back键finish()了自己后, B被销毁的过程中, 并没有调用onSaveInstanceState(), 是因为B并没有被压入task的back stack中,
也即系统知道B并不需要储存自己的状态.
正常情况下, 返回到A, A没有被销毁, 也不会调用onRestoreInstanceState(), 因为所有的状态都还在, 并不需要重建.

如果我们打开了Do not keep activities开关, 模拟系统内存不足时的行为, 从A到B, 可以看到当B resume的时候A会一路走到onDestroy(),
而关掉B之后, A会从onCreate()开始走, 此时onCreate()的参数bundle就不为空了, onStart()之后会调用onRestoreInstanceState()方法, 其参数bundle中内容类似于如下:

Bundle[{android:viewHierarchyState=Bundle[mParcelledData.dataSize=272]}]

其中包含了View的状态, 如果有Fragment, 也会包含Fragment的状态, 其实质是保存了FragmentManagerState, 内容类似于如下:

Bundle[{android:viewHierarchyState=Bundle[{android:views={16908290=android.view.AbsSavedState$1@bc382e7, 2131492950=CompoundButton.SavedState{4034f96 checked=true}, 2131492951=android.view.AbsSavedState$1@bc382e7}}], android:fragments=android.app.FragmentManagerState@bacc717}]

对于上面的例子来说, B什么时候会调用onSaveInstanceState()呢?
当从A打开B之后, 按下Home键, B就会调用onSaveInstanceState().
因为这时候系统不知道用户什么时候会返回, 有可能会把B也销毁了, 所以保存一下它的状态.
如果下次回来它没有被重建, onRestoreInstanceState()就不会被调用, 如果它被重建了, onRestoreInstanceState()才会被调用.

Activity保存方法的调用时机

activity的onSaveInstanceState()onRestoreInstanceState()方法在如下情形下会调用:

  1. 屏幕旋转重建: 先save再restore.
  2. 启动另一个activity: 当前activity在离开前会save, 返回时如果因为被系统杀死需要重建, 则会从onCreate()重新开始生命周期, 调用onRestoreInstanceState(); 如果没有重建, 则不会调用onCreate(), 也不会调用onRestoreInstanceState(), 生命周期从onRestart()开始, 接着onStart()和onResume().
  3. 按Home键的情形和启动另一个activity一样, 当前activity在离开前会save, 用户再次点击应用图标返回时, 如果重建发生, 则会调用onCreate()和onRestoreInstanceState(); 如果activity不需要重建, 只是onRestart(), 则不会调用onRestoreInstanceState().

Activity恢复方法的调用时机

activity的onSaveInstanceState()onRestoreInstanceState()方法在如下情形下不会调用:

  1. 用户主动finish()掉的activity不会调用onSaveInstanceState(), 包括主动按back退出的情况.
  2. 新建的activity, 从onCreate()开始, 不会调用onRestoreInstanceState().

Activity中还需要手动恢复什么

如上, 系统已经为我们恢复了activity中的各种view和fragment, 那么我们自己需要保存和恢复一些什么呢?
答案是成员变量值.

因为系统并不知道你的各种成员变量有什么用, 哪些值需要保存, 所以

首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java 策略模式和状态模式 下一篇Android Fragment使用(三) Activi..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目