Activity, Fragment, WebView的状态保存和恢复

本文详细探讨了Android中Activity和Fragment的状态保存与恢复,包括何时需要恢复、系统如何处理以及手动保存成员变量。特别讨论了Fragment的实例状态、View状态以及与Activity的关系,并讲解了WebView的状态保存恢复,还提到了工具Icepick的使用,以简化状态保存过程。
摘要由CSDN通过智能技术生成

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层面基本的恢复工作, 主要是依靠下面两个方法:

@OverrideprotectedvoidonSaveInstanceState(Bundle outState){        super.onSaveInstanceState(outState);        // 在onStop()之前调用, 文档中说并不保证在onPause()的之前还是之后// 我的试验中一般是在onPause()之后    }    @OverrideprotectedvoidonRestoreInstanceState(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(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值