最近作项目的时候碰到一个棘手的问题,花了很多时间才找到缘由并解决。特此记录这个被我踩过的坑,但愿其余朋友遇到此问题不要调到这坑里去了。html
问题描述:android
一、背景:个人app中某个界面的Activity是继承FragmentActivity,由于此界面包含两个Fragment。这里我称为FragmentA和FragmentB吧。在Activity中有个刷新按钮,用来刷新ViewPager当前Fragment内容的刷新。点击Activity的刷新按钮以后,刷新按钮须要有简单的旋转动画,等Fragment里面的刷新结束以后,会使用getActivity通知Activity结束刷新按钮的刷新动画。以上就是个人业务场景,说简单点就是Fragment须要与它附属的Activity进行通讯。app
二、问题:当应用程序运行到该Activity时,按Home键将该应用程序放置后台运行,去其余app转转。一段时间后,又回到该应用程序,仍是在以前的那个Activity。这时我想刷新一下Fragment里面的内容,点击了Activity界面上的刷新按钮,结果程序crash了。ide
问题分析:post
刚开始遇到该问题时,查看奔溃日志,发现是空指针异常。由于这种场景很少,因此只是简单的加上非空判断就没在乎这个问题了。到后面换了个测试机器,配置不是很好(只有512M运行内存),结果此问题频繁地出现,开始引发个人重视了。因为经验不是很足,此问题不知道怎么重现,因此很难找出问题的根本缘由。后来终于在网上找到了一篇和我遇到一样问题的朋友的帖子,才知道出现这个问题的缘由所在。测试
原来Activity切换到后台以后,因为内存不够,此Activity被系统回收了,一段时间以后回到该应用程序,Activity被从新实例化了。而Activity被系统销毁时,附属在该Activity的Fragment并无被销毁,在Activity的onSaveInstanceState里面将Fragment状态保存起来了,因此Activity从新建立了,可是FragmentA和FragmentB仍是以前的,而此时FragmentA和FragmentB所附属的Activity已经被系统回收了,此次再调用getActivity时返回了null,才致使上面问题的出现。动画
咱们看看FragmentActivity源码中的onSaveInstanceState方法:spa
1 protected void onSaveInstanceState(Bundle outState) 2 { 3 super.onSaveInstanceState(outState); 4 Parcelable p = mFragments.saveAllState(); 5 if (p != null) { 6 outState.putParcelable("android:support:fragments", p); 7 } 8 }
由上面源码能够看出,FragmentActivity确实在onSaveInstanceState方法里面将Fragment的状态保存了。.net
问题解决:指针
知道问题的缘由了,就好办了。解决方法其实很简单,咱们只要让FragmentActivity被系统回收的时候,不保存Fragment的状态便可,即在FragmentActivity中重写onSaveInstanceState方法,而且注释掉super.onSaveInstanceState(outState)就好了。
1 @Override 2 protected void onSaveInstanceState(Bundle outState) { 3 // super.onSaveInstanceState(outState); 4 }
总结:
一、程序出现问题时,要先找出出现此问题的缘由,对症下药才能从根本上解决问题。
二、对于Activity被系统回收致使的问题,可使用切换横竖屏来模拟场景。
最后感谢写http://my.oschina.net/u/1011854/blog/469138这篇帖子的朋友。