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

摘要:
Android紧急情况下活动数据的存储和恢复写在前面:在使用我们的APP的过程中,总是有可能滑倒、在后台被按下,甚至突然被杀死。因此,我们需要以正确的方式保存或恢复APP中的一些临时数据或关键持久数据。紧急情况是什么?因为本文讨论了发生某些紧急情况时数据的存储和恢复。那么,紧急情况是什么?点击后退按钮,点击锁屏按钮,点击主页按钮进入其他APP
Android中突发情况Activity数据的保存和恢复

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

突发情况都有哪些?

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

      • 点击back键

      • 点击锁屏键

      • 点击home键

      • 其他APP进入前台

      • 启动了另一个Activity

      • 屏幕方向旋转

      • APP被Kill

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

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

      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方法保存。

      免责声明:文章转载自《Android中突发情况Activity数据的保存和恢复》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

      上篇Java内存模型(JMM)详解部署zabbix企业监控平台下篇

      宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

      相关文章

      QT 5.4.1 for Android Windows环境搭建

      QT 5.4.1 for Android Windows环境搭建2015-5-13       目录 一、参考文章:  二、准备软件:  三、安装准备好的软件:  四、配置Qt 5.4.1 for Android  五、解决 Creator Qt Quick 模拟层已崩溃  六、解决没有 kit selection(构建套件(Kit))  七、解决编译出错...

      【Android】Android中线程的应用

      1. Android进程    在了解Android线程之前得先了解一下Android的进程。当一个程序第一次启动的时候,Android会启动一个LINUX进程和一个主线程。默认的情况下,所有该程序的组件都将在该进程和线程中运行。同时,Android会为每个应用程序分配一个单独的LINUX用户。Android会尽量保留一个正在运行进程,只在内存资源出现不足...

      【转载】Android属性动画和视图动画的区别

      提起动画首先想到的是动画片,童年最爱的黑猫警长,葫芦娃,邋遢大王,大脸猫和蓝皮鼠,四驱兄弟,七龙珠等等,当时觉着好神奇,他们是怎么动的呢。动画其实就是一帧帧的画面顺序播放,只要画面切换的够快,会我们眼中形成视觉残留的效果,人眼不会感觉到突兀也就会认为画面是连续运动的,至于24帧什么的这里就不说了,现在的手机普遍支持60帧每秒,微鲸的vr设备好像87帧每秒...

      Android开发 BottomNavigationView学习

      前言  注意这个里介绍的是AndroidX的com.google.android.material.bottomnavigation.BottomNavigationView xml布局中 <com.google.android.material.bottomnavigation.BottomNavigationView and...

      Android Activity 切换动画(非原创)

      在Android开发过程中,经常会碰到Activity之间的切换效果的问题,下面介绍一下如何实现左右滑动的切换效果,首先了解一下Activity切换的实现,从Android2.0开始在Activity增加了一个方法: public voidoverridePendingTransition(int enterAnim, int exitAnim) 其中:...

      Oracle存储过程记录异常日志

        一般我们会将一些涉及到数据库的定时任务直接用存储过程搞定,省去了后端代码的开发、部署,简单、快速,但这种方式存在一个弊端——当存储过程执行出错了,我们无法感知。解决办法也简单,学代码那样去捕获异常、打印日志。   第一步,建日志表: create table TBL_WLF_SYS_LOG ( S_TIME VAR...