`
danlov
  • 浏览: 28258 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

利用onSaveInstanceState()回调函数增强程序健壮性

 
阅读更多
      Android有个机制,没有被程序主动销毁的Activity会被放入内存,其销毁由系统根据内存使用情况进行控制。所以在后台的Activity什么时候会被系统干掉我们没办法预见,而且被系统干掉的Activity,系统有时候会帮我们重新创建。
      其实onSaveInstanceState()主要用来辅助系统重新创建Activity时恢复数据的,因为不重新创建的话,也没必要用onSaveInstanceState()保存数据,而且该重建完全是系统来做的,不是我们主动去调用的。
      举个例子来说明:调用系统拍照,拍好照后将照片再显示于我们的Activity上。
正常过程如下:MyActivity1->拍照功能-->MyActivity1。
但是当内存不太够用时,我们的Activity在打开拍照功能后,很容易被系统主动干掉,这是因为拍照要消耗大量资源。但是MyActivity被干掉后,从拍照程序返回,系统为保证这一过程的完整性,会再帮我们主动创建一个MyActivity。
销毁重建过程如下:MyActivity1->拍照功能-->MyActivity2。
这样就出现问题了,MyActivity1与MyActivity2是同一类的两个不同的对象,而MyActivity1中由于用户的操作,会创建一些对象,而系统在创建MyActivity2时,只会调用Activity创建时需要的生命周期函数,最后在MyActivity2中一部分对象丢失了。这时onSaveInstanceState()出场了,它可以保存我们创建的对象,然后供恢复用。
     Bundle中的数据保存到了哪里?
   该问题本人查了很多资料也没有找到明确的答案,只能推导一下了。有个明确的说法是onSaveInstanceState()不能保存持久性数据,通过这个说法,数据应该不是保存到了SD卡中,那么只能是保存在内存中了。
   经过测试,发现不同进程之间调用时,在进程被干掉之前用onSaveInstanceState()保存的数据,在返回后,系统帮忙重新建的进程能恢复数据。这说明一个问题,即Bundle中的数据不是保存在应用所属的进程内存里。参考到Bundle中的对象必须要序列化,或者实现Parcelable接口,不管如何,肯定是为了进程间通信用的。
   所以本人认为Bundle中的数据保存到了系统级进程中的内存里。只要系统没崩溃,保存的数据都能恢复过来。
      onSaveInstanceState()函数是什么时候被系统调用的?
   有个说法:该方法是在系统内存不足时,系统主动销毁Activity前,被调用。
其实该说法不准确,应该是在Activity由前台变为后台时,就会被调用,比如按了Home键或者转跳转到另一个Activity且没被finish,系统都会调用该方法。只要系统认为Activity有被销毁的可能时,就会触发调用,不必等到被销毁前的那一刻。
       如何恢复被保存的数据?
   很明显恢复里需要用到保存时的Bundle对象,因为保存时填入的值都保存在那里,所以恢复用到它,系统提供了两个回调函数,并在参数中提供该Bundle对象:onCreate(Bundle savedInstanceState)、onRestoreInstanceState(Bundle savedInstanceState)。
   是不是onSaveInstanceState被调用了,onCreate中的Bundle就有值或者onRestoreInstanceState函数就会被调用?显然不是的,还原有个条件,即Activity是被系统销毁的,而不是我们主动finish掉的。
   有两个函数都能还原,那应该用哪一个呢?这个完全由实际情况来决定,比如有些对象在onCreate中创建的,或者产生的,并且用到了,那么肯定在onCreate中就要还原该对象,其它情况则选其中之一都可以。主要原因就是这两函数的回调时机不一样,onCreate很明显是Activity创建时首个调用的函数,且只要是新创建的,都会调用,而onRestoreInstanceState函数是在onStart后,onResume之前被调用的。
  
  
       
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics