本文主要是介绍深夜记一个大坑:illegalStateException:can not perform this action after onSaveInstanceState,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
好吧,其实重点不在于这个Excpetion…
项目采用了MVP模式,有1个Activity,3个Fragment,通过Presenter来切换Fragment,其中,Presenter中创建并保存了这3个Fragment的实例(避免不断的重复创建新的实例)
我在用AlarmManager设置了一个闹铃提醒(其context 是MainActivity),
这个提醒会启动一个BroadcastReceiver,在这个BroadcastReceiver中,我需要去更新UI,,,
本来嘛,一开始,出于条件反射,就想使用Handler,然后,由于太懒(应该还是条件反射哈哈),用Handler实在是太麻烦了。
于是,我灵机一动(坑了自己一把),就想把Presenter写成单例
然后就可以在BroadcastReceiver中调用到Presenter了,然后就可以轻易的更新UI!!
然后,然后,,
一切执行得很顺利,一直到我手贱打开app,退出app,又打开app,,,咦,怎么变空白了???
一时间感觉摸不着头脑,然后我试着切换到另一个Fragment,,,没错,出现了标题中的那个异常,W……T……F……这什么鬼,明明是在onCreate中执行commit的啊,,,好吧,然而明明并帮不了我
然后便上google到stackoverflow等站遨游一番。。
以下便是采集到的战果:
- 在onResume中执行commit(3.0以前)
- 在onPostResume中执行commit(3.0及以后)
- 在onResumeFragments中执行commit
- 重写onSaveInstanceState,让其实现为空
- 还有著名的”用commitAllowStateLoss来替代commit“
- 重写Activity的onBackPress方法
这么多方法,前后查找包括测试就花了2个多小时(包括很多无果的查找和测试)。。。。然并卵
于是,我继续到处搜查,
直到,,我看到了一篇文章说明的情况和我非常的相似:使用AlarmManager设置闹钟,AlarmActivity接收提醒并做UI更新(他是创建DialogFragment)……
好吧,看完一堆说明之后,我发现跟他还是 不!一!样!
不一样在什么地方呢,不一样在他是使用了上面提到的方法解决的。。
然后我就开始受不了,这这这世界是怎么了,怎么连google都解决不了了。。
然后,我想起了一句话:最难跳出的坑总是你自己设下的。。(好吧,这是我说的)
于是我不再google,开始自己一点一点的调试,在某个瞬间,突然觉得自己像傻逼一样:既然页面空白,那应该首先考虑到是不是Fragment没有初始化呢……(这个时候,我开始意识到真正的错误不是那个异常,而是有幕后黑手,而这个黑手就是我自己培养出来的。。)
然后,我测试了几个Fragment的onCreate方法和onDestroy方法,我打开app,关闭app,打开app,,果然不出我所料!这些方法都只执行了一遍!!
然后就想到一件原先意想不到的事情,Activity销毁后,Presenter单例并没有被销毁!!一测试果不其然。
到这里,就知道为什么报那个异常了吧:Fragment已经被销毁(执行了onDestroy方法,是 “After onSaveInstanceState”的),然后我重新打开app,并没有创建新的Fragment,就执行了commit
至于静态的Presenter为什么不会被销毁呢,好吧,我确实不知道,怪我孤陋寡闻。
然后随便一查,单例所造成的内存泄漏
看到这篇文章 说到静态变量销毁的2种情况:
1. 进程死了
2. 所在上下文从ClassLoader里面卸载了
至此,明白了此次bug造成的原因,,果然还是自己造的坑容易进难出。。。。
最后,我当然还是要使用单例的,毕竟对handler实在是反感,怎么办呢,现在就好办了,在Activity的onDestroy方法中释放Presenter即可。
这篇关于深夜记一个大坑:illegalStateException:can not perform this action after onSaveInstanceState的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!