使用onSaveInstanceState和onRestoreInstanceState来保存恢复被系统销毁的数据

来源:互联网 发布:阿里云销售经理收入 编辑:程序博客网 时间:2024/04/30 16:45
开发项目时有遇到这样一个问题:程序长时间打开,使用一会其他应用或者打开比较占内存的应用后,再次回到开发的项目,程序就会崩溃,查看错误信息是NullPointException。到底是为什么呢?经过我跟另一个同事长期观察、测试、总结发现我们在项目中使用了大量的静态变量,报错的地方都是使用了静态变量。

空异常的原因应该是java虚拟机的垃圾回收机制主动回收没有被引用的对象,在内存不足的时候,虚拟机主动回收处于后台的Activity、Service,所以当再次回到这个页面的时候,数据已经被回收,没有恢复,所以报NullPointException。

在这篇文章中http://blog.csdn.net/weihan1314/article/details/8033052作者遇到与我们相同的问题,静态变量使用误区。
如果不是用全局静态变量,那在Activity或其他组件中怎么使用全局变量呢?在android中还有一个组件——Application,它是与应用同时存在的,也就是应用在它就在,并不会被GC给莫名其妙的回收掉,在android application学习
这篇文章中介绍了怎么安全的使用全局变量。

但是现在的问题是,我们的应用都已经快完工,如果把全局变量都修改,感觉不现实。这将是一个巨大的工程。于是继续看帖学习。发现了Activity中的两个方法onSaveInstanceState和onRestoreInstanceState这两个方法。

(这两个帖子中作者介绍了两个方法的使用情况)
http://www.cnblogs.com/SharkBin/p/3539658.html
http://jingyan.baidu.com/article/215817f7d79b891eda14231b.html

不属于Activity生命周期中的方法。它们不同于 onCreate()、onPause()等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity时,onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。

  在activity被杀掉之前调用保存每个实例的状态,以保证该状态可以在onCreate(Bundle)或者onRestoreInstanceState(Bundle) (传入的Bundle参数是由onSaveInstanceState封装好的)中恢复。这个方法在一个activity被杀死前调用,当该activity在将来某个时刻回来时可以恢复其先前状态。 


那么我是怎么使用这两个方法来保存我想要的数据呢?看一下代码:

 

/**  * 保存状态  */ @Override protected void onSaveInstanceState(Bundle outState) {   String json_user = JSONUtils.toJson(Constants.USER);//把要保存的静态全局变量先转成Json  outState.putString("json_user", json_user);    super.onSaveInstanceState(outState); } /**  * 恢复数据  * @param savedInstanceState  */ public void resaveInstanceState(Bundle savedInstanceState){   if (savedInstanceState == null) {   return;  }   String json_user = savedInstanceState.getString("json_user");   if(json_user != null && !json_user.equals("")){    Constants.USER = JSONUtils.fromJson(json_user, User.class);   }}

然后很重要的一个步骤是在 onCreate方法中初始化 resaveInstanceState(savedInstanceState)这个方法,这个方法是自定义的方法。

@Override protected void onCreate(Bundle savedInstanceState) {  setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  super.onCreate(savedInstanceState);  resaveInstanceState(savedInstanceState);  init(); }



如果使用Activity中onRestoreInstanceState(Bundle savedInstanceState) 方法有个弊端是,每次恢复数据前是先onCreate()Activity 的,所以对于我们遇到的问题还是没有解决,如果想要用封装好的方法,又要修改很多数据,给需要恢复数据的地方放个默认值。当调用onRestoreInstanceState(Bundle savedInstanceState)方法后再刷新页面。

 @Override protected void onRestoreInstanceState(Bundle savedInstanceState) {  // TODO Auto-generated method stub  super.onRestoreInstanceState(savedInstanceState); }


所以用了自定义的方法自定义方法也有个弊端,就是当activity调用onPause()方法时数据就会被恢复。


0 0
原创粉丝点击