1、前言
当Android系统的运行内存不足时,会把运行在后台的应用杀掉,将所有已经存在的Activity都杀掉,当用户重新返回应用的时候,所有被杀掉的Activity都会被重建,而且应用会运行在一个全新的进程当中,所有的数据都被重置为初始状态。那么这个时候往往都会出现错误数据。
2、案例:
XX应用,在登录页初始化所有数据
--> 登录成功进入主页面
--> 此时登陆页已经完成任务,finish登陆页
--> 从主页面进入到A页面
--> A页面通过网络加载数据
--> 点击Home键,打开其他耗内存的应用,此时如果内存不够,会把XX应用的主页面和A页面都干掉,当再返回XX应用时,主页面和A页面都会重建,经历onCreate方法等。
3、如何触发以上案例:
XX应用现在的手机基本上运行内存都足够了,但是还是会有开太多应用导致内存不够的时候,如果使用真机来重现以上案例,需要开的应用就多了,那么如何轻易的就实现以上案例呢?很简单,可以通过虚拟机,下载Genymotion,建一个虚拟机,将虚拟机的运行内存改为150M-200M左右,基本上就足够一个应用运行但不够两个应用一起运行了。
重现案例的条件已经具备了,接下来就是如何通过代码Log来实验了。
4、代码分析:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Log.e("YYQ", "onCreate");
}
@Override
protected void onStart()
{
super.onStart();
Log.e("YYQ", "onStart");
}
@Override
protected void onResume()
{
super.onResume();
Log.e("YYQ", "onResume" + android.os.Process.myPid());
}
@Override
protected void onPause()
{
super.onPause();
Log.e("YYQ", "onPause");
}
@Override
protected void onStop()
{
super.onStop();
Log.e("YYQ", "onStop");
}
@Override
protected void onDestroy()
{
super.onDestroy();
Log.e("YYQ", "onDestroy");
}
@Override
protected void onRestart()
{
super.onRestart();
Log.e("YYQ", "onRestart");
}
// 这个方法不知道是什么时候触发的
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)
{
super.onSaveInstanceState(outState, outPersistentState);
Log.e("YYQ", "onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)");
}
<pre name="code" class="java">// 当后台运行应用时,此方法会被触发
@Override
protected void onSaveInstanceState(Bundle outState)
{
// 在这里保存相关信息
outState.putString("test","save msg");
super.onSaveInstanceState(outState);
Log.e("YYQ", "onSaveInstanceState(Bundle outState)");
}
// 当内存不足应用被干掉后,重新回到应用,此方法被触发
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
super.onRestoreInstanceState(savedInstanceState);
// 在这里取回相关信息
Log.e("YYQ", "test是:"+savedInstanceState.getString("test"));
Log.e("YYQ", "onRestoreInstanceState");
}
在Activity中加入如上方法,就可以在Log中查看Activity的状态了。
正常的Activity状态就不说了,
当你按下Home键,会触发
onPause
onSaveInstanceState(Bundle outState)
onStop
比较重要的是onSaveInstanceState(Bundle outState),当系统未经你的允许就想要把Activity干掉的时候,这个方法会被触发,你可以在这里进行保存的操作。
此时应用已经在后台运行了,当你没有打开其他应用,也就是内存足够的时候,重新返回的时候不会触发onRestoreInstanceState方法,只有应用被干掉了,才会触发onRestoreInstanceState方法,还有onCreate方法。
onCreate
onStart
onRestoreInstanceState
onResume
在onCreate方法加入:
@Override
protected void onResume()
{
super.onResume();
Log.e("YYQ", "onResume:" + android.os.Process.myPid());
}
会发现你刚启动应用时的pid和应用被杀掉后重建的pid不一样,说明应用在新进程中了。
你可以在onRestoreInstanceState方法中恢复数据。
5、解决方式:
虽然可以在onSaveInstanceState(Bundle outState)和onRestoreInstanceState方法中进行保存和恢复数据,但是对于一些全局性的数据最好能够一次性恢复,这样对于所有的Activity都有好处。
可以在基类Activity中一次性恢复。(一般应用都会有个自己的基类BaseActivity,用于抽取Activity的共性)
在onCreate方法中加入判断:
if (savedInstanceState != null && TextUtils.isEmpty(
BaseApplication.getInstance().getCurrentUser().getSystemUserID()))
{
BaseApplication.getInstance().initUserAllData();
}
其中第二个判断条件和if语句块是根据个人情况来的,我在这里的判断是当用户的id为null时,就说明Activity已经被重建了,数据被清除了,那么我就再次初始化用户的数据。保证了用户数据的完整性。
第一个判断条件只有当调用了onSaveInstanceState(Bundle outState)方法,并且应用被杀掉后,才不为null。
如此一来,就不怕内存不够的时候了,而且初始化用户数据也不会被多次初始化。