Android应用在内存不足被KILL时如何保存与恢复数据

    近项目中出现一个bug在登录应用然后HOME键使用其他应用然后回到刚才的应用提示你下线重新登录,找了好久才发现是手机内存不足,应用被系统kill。Android独特的内存机制,导致系统内存不足时会销毁后台的应用,这里我们研究一下应用被销毁后重新加载时的情形
一个安卓应用A先后打开3个Activity: a –> b –> c 这个时候如果来了一个电话, 接电话的过程中, 手机内存不够, 那么应用A将会被系统回收当打完电话,再次进入应用A的时候会发生下面的事情:
1、系统会重新加载c,而且是在新线程中
2、现在点返回关闭c,系统就会重新加载b,而且是在新的线程中(跟c不是一个线程)
3、现在点返回关闭b,系统就会重新加载a,而且是在新的线程中(跟c,b的线程都不相同)
(就是先打开c,finish了c时加载b,finish了b时加载a)

注意: 这个时候应用中的全局静态变量将全部重置有默认值的为默认值,没有默认值的为null)

这时如何你是登录状态并且登录信息保存在全局变量中,那个将会告知你要重新登录,你会说登录信息用SharedPreferences保存用户登录状态,但是有的情况下,银行基金类应用为安全是需要每次打开登录验证通过session控制登录超时的,此时就不适合保存本地。然而后台在内存不足时kill掉应用,难道每次都让用户再次登录吗?我想用户也疯了。当让Android有考虑在应用kill之前有保存数据的机会就是onSaveInstanceState方法。
如过对onSaveInstanceState不是很了的,这里有篇博客关于Activity的onSaveInstanceState调用时机的说明

onSaveInstanceState方法会在什么时候被执行,有这么几种情况:
1、当用户按下HOME键时。
这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则
2、长按HOME键,选择运行其他的程序时。
3、按下电源按键(关闭屏幕显示)时。
4、从activity A中启动一个新的activity时。
5、屏幕方向切换时,例如从竖屏切换到横屏时。
在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行。
6、应用在后台内存不足,系统kill时

总而言之,onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。

那么如何使用onSaveInstanceState来在“未经你许可”时销毁了你的activity时保存数据呢。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState!=null){
String userId=savedInstanceState.getString("userId");
String userName=savedInstanceState.getString("userName");
}
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("userId", 1234 + "");
outState.putString("userName", "4321");
}

具体你可以根据需求保存任何复杂的数据都可以。