今天测试提交了一个bug,“启动应用,按下home键,玩玩其他的应用,然后在点击该应用,应用直接崩溃了!”
首先查看了应用崩溃日志,发现不是经常报这个空指针,就是报那个空指针导致的(按下Home键是处于不同的界面),再然后就是报“ Unable to start activity ComponentInfo{com.hbss.smarterstore/com.xx.yy.ui.MainActivity}: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.xx.yy.ui.shopinfo.ShopDetailFragment: make sure class name exists, is public, and has an empty constructor that is public ”这个也报的很多。
我们都知道,如果系统内存不足、或者切换横竖屏、或者app长时间在后台运行,Activity都可能会被系统回收,然后Fragment并不会随着Activity的回收而被回收,从而导致Fragment丢失对应的Activity。 而我的应用中就使用了很多Fragment,所以原因肯定是这个。
当应用在在台正常操作时,是没有报过这些错误的,所以肯定还是activity被销毁了导致的。
原来Activity切换到后台之后,由于内存不够,此Activity被系统回收了,一段时间之后回到该应用程序,Activity被重新实例化了。而Activity被系统销毁时,附属在该Activity的Fragment并没有被销毁,在Activity的onSaveInstanceState里面将Fragment状态保存起来了,所以Activity重新创建了,但是FragmentA和FragmentB还是之前的,而此时FragmentA和FragmentB所附属的Activity已经被系统回收了,这次再调用getActivity时返回了null,才导致上面问题的出现。
由上面源码可以看出,FragmentActivity确实在onSaveInstanceState方法里面将Fragment的状态保存了。 知道问题的原因了,就好办了。解决方法其实很简单,我们只要让FragmentActivity被系统回收的时候,不保存Fragment的状态即可,即在FragmentActivity中重写onSaveInstanceState方法,并且注释掉super.onSaveInstanceState(outState)就行了。
问题解决!
首先查看了应用崩溃日志,发现不是经常报这个空指针,就是报那个空指针导致的(按下Home键是处于不同的界面),再然后就是报“ Unable to start activity ComponentInfo{com.hbss.smarterstore/com.xx.yy.ui.MainActivity}: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.xx.yy.ui.shopinfo.ShopDetailFragment: make sure class name exists, is public, and has an empty constructor that is public ”这个也报的很多。
我们都知道,如果系统内存不足、或者切换横竖屏、或者app长时间在后台运行,Activity都可能会被系统回收,然后Fragment并不会随着Activity的回收而被回收,从而导致Fragment丢失对应的Activity。 而我的应用中就使用了很多Fragment,所以原因肯定是这个。
当应用在在台正常操作时,是没有报过这些错误的,所以肯定还是activity被销毁了导致的。
原来Activity切换到后台之后,由于内存不够,此Activity被系统回收了,一段时间之后回到该应用程序,Activity被重新实例化了。而Activity被系统销毁时,附属在该Activity的Fragment并没有被销毁,在Activity的onSaveInstanceState里面将Fragment状态保存起来了,所以Activity重新创建了,但是FragmentA和FragmentB还是之前的,而此时FragmentA和FragmentB所附属的Activity已经被系统回收了,这次再调用getActivity时返回了null,才导致上面问题的出现。
我们看看FragmentActivity源码中的onSaveInstanceState方法:
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable("android:support:fragments", p);
}
}
由上面源码可以看出,FragmentActivity确实在onSaveInstanceState方法里面将Fragment的状态保存了。 知道问题的原因了,就好办了。解决方法其实很简单,我们只要让FragmentActivity被系统回收的时候,不保存Fragment的状态即可,即在FragmentActivity中重写onSaveInstanceState方法,并且注释掉super.onSaveInstanceState(outState)就行了。
@Override
protectedvoid onSaveInstanceState(Bundle outState) {
}
问题解决!