android-APP长期运行于后台,重启后如何避免异常
问题的详细描述是这样的:
android中,当我们按home键(一般指手机的物理按钮的中间那个键)回到手机桌面,此时app并没有退出,而是一直运行与后台中,此时如果我们点击app图标,还是会进入刚刚的界面之中。但是这存在一个问题,就是如果内存紧张或者当我们回到桌面,点击了别的应用造成内存紧张,此时再通过点击图标进入app,此时会出现异常。这样造成的用户感觉非常不好!
其实,归纳起来,并不仅仅这种情况下造成数据丢失,造成数据丢失的情况有如下几种:
(1)、当用户按下HOME键时。
这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activityA是否会被销毁,因此系统会调用
onSaveInstanceState(),让用户有机会保存某些非永久性的数据。
(2)、长按HOME键,选择运行其他的程序时。
(3)、按下电源按键(关闭屏幕显示)时。
(4)、从activity A中启动一个新的activity时。(这种情况应该是,当我们在activityA时,此时通知栏有其他的通知,我们点击通知启动activityB,此时我们进入别的应用)
(5)、屏幕方向切换时,例如从竖屏切换到横屏时。
值得幸运的是,android对此提供了非常好的解决办法!
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它们不同于onCreate()、onPause()等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity时,
onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。
在activity被杀掉之前调用保存每个实例的状态,以保证该状态可以在onCreate(Bundle)或者onRestoreInstanceState(Bundle)(传入的Bundle参数是由onSaveInstanceState封装好的)中恢复。这个方法在一个activity被杀死前调用,当该activity在将来某个时刻回来时可以恢复其先前状态。
@Override
protectedvoid onSaveInstanceState(Bundle outState) {
System.out.println(BaseActivity.onSaveInstanceState());
outState.putString(loginname, Application.LOGINNAME);
outState.putInt(classId, Application.classId);
outState.putSerializable(classinfos,
(ArrayList<classinfo>)Application.getInstance().getClassInfos());
super.onSaveInstanceState(outState);
}
@Override
protectedvoid onRestoreInstanceState(Bundle savedInstanceState) {
System.out.println(BaseActivity.onRestoreInstanceState());
super.onRestoreInstanceState(savedInstanceState);
if(savedInstanceState != null) {
Application.LOGINNAME =savedInstanceState.getString(loginname);
Application.classId =savedInstanceState.getInt(classId);
Application.getInstance().setClassInfos(
(List<classinfo>)savedInstanceState.getSerializable(classinfos));
}
}
实例代码如上,通过重写上面两个方法保存一些需要当前界面或者整个应用需要使用的数据,缓存起来,等到重新启动时,这些数据依然存在,这样重启之后不会造成app异常退出!
需要提醒的是,我们开发一个app的时候,activity是非常多的,一个界面中需要的数据很多,并且不知道用户会在哪个activity中按下Home键退回到了手机桌面,这样该如何处理呢?
此时的解决办法是,使用一个基本BaseActivity,在BaseActivity重写onSaveInstanceState和onRestoreInstanceState两个方法,然后每个界面Activity继承基类BaseActivity,这样不必每个activity重写这两个方法,同时,不管在哪个activity中按下home键,都会把数据保存起来,重启之后数据不至于丢失!
———————————— 分隔符—————————————-
另外,还有一个地方需要说明,有些app可能想每次点击应用图标的时候,都能够进入主界面,不管此时app处于什么状态,不管app此时是否运行与后台,这时可以使用activity的配置
<intent-filter>
<categoryandroid:name="android.intent.category.LAUNCHER">
</category></action></intent-filter>
</activity>
启动的activity中配置android:launchMode=”singleTask”即可。这样配置,保证每次点击应用图标,都进入主界面内,不管此时app是否运行与后台之中。