App进程被杀所引发的问题及其处理方案

开始先假设有这样一个简单的情景:当前应用中有3个Activity AAcitity BActivity CActivity在当前的Activity栈中处于栈顶的为C。接着按下home键此时3个activity都处于"stoped"状态。但这种情景下应有有可能会被杀掉。

App进程被杀所引发的问题及其处理方案_第1张图片
stack.png

一 被杀的原因

在官方文档中关于Activity生命周期的部分可以看到这样的描述:

If an activity is paused or stopped, the system can drop the activity from memory by either asking it to finish, or simply killing its process. When it is displayed again to the user, it must be completely restarted and restored to its previous state.

大概的意思是当内存不足的时候应用是可能被"杀"掉的。通过下面文档的表格可以看出,当activity处于stoped、destroyed以及paused(3.0版本以前)的状态时所在进程都有可能被杀掉(当然这里的activity的状态是对应activity栈顶的状态)。

App进程被杀所引发的问题及其处理方案_第2张图片
killabel.png

二 被杀后所产生的现象

  • 可能有人会有这样的疑问:当应用被强杀掉,所有在当前Activity栈中的Activity(此时处于stopped状态)进程被杀掉的时候会像调用finish那样结束掉自己吗?通过测试可以得出答案:不会(你可以通过ddms模拟系统杀掉你的进程进行测试就可以得出这样的结论)。在开头描述的情景下杀掉进程的话,所有Activity都不会走onStop和onDestroy方法。所以这种情况下关闭数据库、文件之类的操作最好考虑放到onPause中进行了。

  • 如果你有在onSaveInstanceState(Bundle)做数据保存的话,这时候就应该要注意了,通过测试你会知道应用被强杀后activity不会调用到onSaveInstanceState(Bundle)(或许这时候你可以考虑提前在onPause()中作相应的处理)。

  • 当应有被杀掉后,你再重新打开应用的话是打开最近可见的activity对应于情景的CActivity,这时候如果你再返回按钮会发现会回到BActivity,当然再按一次就回到AActivity。可见Activity栈并没有因为应用被杀掉而清空。但这里有一点要注意的是,这种情况下栈中Activity重新实例化,因为之前栈中的Activity其实已经被销毁了。这一点可以通过打印应用被杀前后的Activity对象的hash值得到验证。

Paste_Image.png

三 被杀后重新打开可能发生的问题

根据二中提到的现象因为应用被强杀而数据得不到恢复的话可能就会出现问题,例如BActivity启动通过bundle携带数据到CActivity中,但当重新打开应用时数据因为BActivity还没有实例化,CActivty中就获取不到正确的数据了。另外一种可能出现的问题是假设CActivty中使用了BActivity中的静态引用reference,而该引用是随BActivity的实例化而实例化的,所以CActivity中使用的只是一个指向空的引用这样使用就会报空指针了。当然实际开发中在各种情形下因为强杀后再启动应用也会引起其他问题。

四 被杀后的处理

当然最好的处理方法是让数据重新的恢复并且避免三中提及到的以及可能出现的各种问题。但这就要根据具体的项目去做处理了。这里主要介绍另一种方案就是 当重启应用时清空Activity栈并且重新从AActvity开始launcher应用。这样就绕开了数据恢复的问题。但这里注意的一点是假设你在CActivity中根据你所设置的标志判断到应用需要重走流程starActivity的时候,需要将intent的flags设置为

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);

这样做才能把先前的栈清空。

参考文章: http://www.jianshu.com/p/bce1164b83d8

你可能感兴趣的:(App进程被杀所引发的问题及其处理方案)