Android中突发情况Activity数据的保存和恢复

Android中突发情况Activity数据的保存和恢复

写在前面:
在我们的APP使用的过程中,总有可能出现各种手滑、被压在后台、甚至突然被杀死的情况。所以对APP中一些临时数据或关键持久型数据,就需要我们使用正确的方式进行保存或恢复。

突发情况都有哪些?

因为本文讨论的是当一些突发情况的出现时,对数据的保存和恢复。所以现在总结一下突发情况应该都有哪些?

      • 点击back键
      • 点击锁屏键
      • 点击home键
      • 其他APP进入前台
      • 启动了另一个Activity
      • 屏幕方向旋转
      • APP被Kill

当这些突发情况发生的时候,有哪些关键的方法会被调用呢?

写了一个简单的demo,我用上述的突发情况进行测试,代码中我重写了所有Activity的生命周期方法onSaveInstanceState方法,并打印对应的log在控制台,下面是demo图:

这里就不贴出测试的过程了,直接来告诉大家测试的结果吧:

当我的APP处在前台,能与用户交互的情况下,出现上述的突发事件时,只有点击back键onSaveInstanceState方法不会调用。其余的情况下, 该方法一律都会调用,这又是为什么呢?并且onPause方法是必然会调用的,这又给我们保存数据提供了怎样的思路呢?

onSaveInstanceState

好吧,相信当你看到本文标题的时候,你就应该想到了这个方法。因为当我们学习Android基础知识时,用onSaveInstanceState方法进行数据恢复是你必然学到过的。所以前面我营造出的一些悬念看似是失败了,不过对于onSaveInstanceState你理应知道更多知识:

      1. 何时调用:
> Android calls onSaveInstanceState() before the activity becomes vulnerable to being destroyed by the system, but does not bother
calling it when the instance is actually being destroyed by a user
action (such as pressing the BACK key)

找到了以上一段话,翻译过来就是当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。

结合我们以上的例子,其实都在说明一个词,就是**被动**。当Activity并不是由我主动点击back键而丧失焦点时,onSaveInstanceState方法就一定会调用。就例如我上述列举的那些除了点击back键的“**突发情况**”。
      1. 何地调用:

        在我写的这个demo中,onSaveInstanceState的调用是处于onPauseonStop之间的,(下面关于Activity的生命周期方法,会讲解一些值得大家注意的),我查阅了一下资料,能保证的是onSaveInstanceState方法会在onStop之前调用,但是是否在onPause之前就不一定了。

结论: google工程师们对onSaveInstanceState如此设计就是让其完成对一些临时的、非永久数据存储并进行恢复。什么样的数据属于临时数据呢?举个例子,比如EditText中输入的内容,CheckBox是否勾选,ScrollView的滑动位置,目前视频的播放位置等等。

当我还没有自学Android时,玩着一些APP就会产生一个疑问,比如我在一个输入框中输入了大量文字没有提交或者保存。此时来了一个电话,如果退回的时候,输入框里面的文字消失了,那我可能会砸了电话,所以这个保存数据的操作,是Android开发者做的吗?

然而是不需要的,因为Android的View本身自己就实现了onSaveInstanceState方法,这些控件自己就具有保存临时数据和恢复临时数据的能力。

例如TextView中的部分源码:

其他View控件都有相似的实现原理。值得一提的是,只有当你给这个wiget在xml中指定id时,它才具有保存数据并且恢复的能力,并且不同的wiget还不能共用这个id,否则会出现数据覆盖的情况。具体的源码有兴趣大家可以自己去看,这里因为篇幅的原因不再贴出,关于onSaveInstanceState我们先说这些,赶紧看看使用姿势。

onSaveInstanceState的使用姿势

比如我们要保存当前视频的播放进度,这个显然控件没有帮我们实现onSaveInstanceState,所以就只能靠自己了,代码如下所示。


当在onCreate取出临时数据时,记得加一个非空判断

看到这里,也许你认为本文该就此结束了,不过在回过头看看,我们刚才一直强调的是临时数据,毕竟onSaveInstanceState本身就是为临时数据服务的,但是一些永久性质的数据,比如插入数据库的操作,我们应该在什么方法中对其进行保存呢?

onPause

在介绍onPause方法之前,还是想聊聊Activity的生命周期方法,相信大家对它应该有了初步的了解,不过在相应的生命周期方法中,我们应该做什么操作呢?推荐给大家一篇文章,我觉得不错。

Activity生命周期详解

关于onPause,我找到了一下关于它的特性:

onPause(), onStop(), onDestroy() are “killable after” lifecycle methods. This indicates whether or not the system can kill the process hosting the activity at any time after the method returns, without executing another line of the activity’s code. Because onPause() is the first of the three, once the activity is created, onPause() is the last method that’s guaranteed to be called before the process can be killed—if the system must recover memory in an emergency, then onStop() and onDestroy() might not be called. Therefore, you should use onPause() to write crucial persistent data (such as user edits) to storage. However, you should be selective about what information must be retained during onPause(), because any blocking procedures in this method block the transition to the next activity and slow the user experience.

翻译过来就是:无论出现怎样的情况,比如程序突然死亡了,能保证的就是onPause方法是一定会调用的,而onStop和onDestory方法并不一定,所以这个特性使得onPause是持久化相关数据的最后的可靠时机。当然onPause方法不能做大量的操作,这会影响下一个Activity入栈。

刚才我们的测试结果还说明了一个道理,onSaveInstanceState并不是百分百调用的(比如点击了back键),显然一些永久性的数据,我们并不能在此中保存。

关于本文的结论就显而易见了,我们来一句话总结一下:

临时数据使用onSaveInstanceState保存恢复,永久性数据使用onPause方法保存。

时间: 2024-08-04 01:13:13

Android中突发情况Activity数据的保存和恢复的相关文章

android 中View, Window, Activity, WindowManager,ViewRoot几者之间的关系

(1)View:最基本的UI组件,表示屏幕上的一个矩形区域. (2)Window: 表示一个窗口,不一定有屏幕那么大,可以很大也可以很小: 它包含一个View tree和窗口的layout 参数. View tree的root View可以通过getDecorView得到.还可以设置Window的Content View. (3)Activity:Activity包含一个Window,该Window在Activity的attach方法中通过调用 PolicyManager.makeNewWind

android中fragment和activity之间相互通信

在用到fragment的时候,老是会遇到一个问题,就是fragment与activity之间的通信.下面就来记录一下activity和fragment之间 通过实现接口来互相通信的方法. 1. activity 向fragment发出通信,就这么写: private OnMainListener mainListener; // 绑定接口 @Override public void onAttachFragment(Fragmentfragment) { try { mainListener =

Android中多个Activity继承自己写的父容器(Activity)

如果你的一个应用里面有几个不同的页面却需要设置一些相同的东西,那么,我觉得应该尝试着用父容器,开始自己就是不知道这个概念,弄得自己写了太多的不应该的代码....所谓的程序.....苦煞也.. 在父容器里面,我们可以统一相同的title,以及·相同的背景页面... 这里我给出一个连接哦,不懂的,就可以嘿咻嘿咻..http://pan.baidu.com/s/1sjBDPbn Android中多个Activity继承自己写的父容器(Activity),布布扣,bubuko.com

IOS中利用NSKeyedArchiver进行数据的归档和恢复

1.相关知识点: <1> 可以利用NSKeyedArchiver 进行归档和恢复的对象类型:NSString .NSDictionary.NSArray.NSData.                        NSNumber等 <2> 使用是必须遵循NSCoding协议对象,实现两个方法: encodeWithCoder:归档对象时,将会调用该方法. initWithCoder:每次从文件中恢复对象时,调用该方法. 2.简单例子阐述详细步骤 <1> 创建一个学生

Android开发中Activity状态的保存与恢复

当置于后台的Activity因内存紧张被系统自动回收的时候,再次启动它的话他会重新调用onCretae()从而丢失了之前置于后台前的状态. 这时候就要重写Activity的两个方法来保存和恢复状态,具体用途举个例子:你正在编辑短信,这时候来了一个电话,打完电话回到短信界面, 短信刚好被系统回收重启,这时原先编辑了一半的内容总不能丢失了吧,这样影响用户体验.所以解决办法如下: 1 private static final String INSTANCE_STATUS="instance_statu

Android中Fragment与Activity之间的交互(两种实现方式)

(未给Fragment的布局设置BackGound) 之前关于Android中Fragment的概念以及创建方式,我专门写了一篇博文<Android中Fragment的两种创建方式>,就如何创建Fragment混合布局做了详细的分析,今天就来详细说道说道Fragment与宿主Activity之间是如何实现数据交互的. 我们可以这样理解,宿主Activity中的Fragment之间要实现信息交互,就必须通过宿主Activity,Fragment之间是不可能直接实现信息交互的. Fragment与

Android中Fragment和Activity之间的互操作代码例子

摘要 本文介绍了Android中一个Activity中有多个Fragment的情况下,Fragment之间如何通过Activity进行互操作. 源代码 源代码地址为:http://download.csdn.net/detail/logicteamleader/8931199 源代码使用ADT编写,ADT版本为2014,Android版本为android-22. 技术要点 1.在Activity中的多个Fragment之间要互操作,一定要通过此Activity,不能直接通信: 2.在Activi

android中关闭所有activity方法

在android中退出app时关闭所有Activity的方式有很多,例如发送一个全局的BroadCast.直接杀死当前的pid...但是如果我们做的功能是一个sdk那情况就不一样了..经过项目上线后惨痛的教训我们决定还是通过自定义Stack来管理我们的activity. 首先说说这个坑人的BroadCast,因为我们发送的是无序广播,不知道那个Activity会先收到,这个导致了一个严重的问题==后收到广播的Activity会重绘而我们的需求是不希望activity被重新创建bug一大堆:其次我

Android中intent启动Activity中intent.setFlags()的作用

Intent.setFlags()函数用法: Intent的常用Flag参数: FLAG_ACTIVITY_CLEAR_TOP:例如现在的栈情况为:A B C D .D此时通过intent跳转到B,如果这个intent添加FLAG_ACTIVITY_CLEAR_TOP标记,则栈情况变为:A B.如果没有添加这个标记,则栈情况将会变成:A B C D B.也就是说,如果添加了FLAG_ACTIVITY_CLEAR_TOP标记,并且目标Activity在栈中已经存在,则将会把位于该目标activit