cannot perform this action after onsaveinstancestate

今天遇到了这个问题, 报错信息是:cannot perform this action after onsaveinstancestate。百度了一下,都说将commit替换成commitAllowingStateLoss就可以了。(我的问题在于在onResume()方法内使用fragment的commit)这样替换的确解决了问题,但是后来仔细研究了下才发现事情没这么简单。

抛出异常的原因

众所周知,Android系统可以为了释放资源在任意时刻终止进程,有些后台运行的进程可能都不会有任何提示的被杀。而onSaveInstanceState()就是给activity一个最后机会去保存它需要保存的东西,bundle对象就是所要保存信息的载体被传到系统服务进程,如果有朝一日该activity被重新创建时,该对象就会被传回帮助activity重现先前的状态。那么抛出异常的原因在哪儿呢?事实上bundle对象仅仅是activity在调用onSaveInstanceState()时的快照,也就意味着在onSaveInstanceState()后使用FragmentTransaction#commit()时,bundle并没有对该transaction作保存而在activity还未恢复到最初状态时调用,这样便会出现UI的丢失,为了保护用户体验IllegalStateException就被抛出了。
版本差异

file:///C:\Users\lawson\AppData\Roaming\Tencent\Users\708940440\QQ\WinTemp\RichOle\X36K}S9JCU%E25Y1M]0LX50.jpg

file:///C:\Users\lawson\AppData\Roaming\Tencent\Users\708940440\QQ\WinTemp\RichOle\X36K}S9JCU%E25Y1M]0LX50.jpg



如何避免

1 在activity生命周期方法内使用FragmentTransaction#commit()应谨慎
   多数的应用会在onCreate()中使用该方法,所以不会遇到这样的问题,但如果在onActivityResult(), onStart()或onResume()中使用时就有可能遇到了。那么如果因为一些原因一定要在这些方法中使用FragmentTransaction#commit()该怎么办呢(比如说从下一个页面回来时需要刷新界面的时候)。这时最好在 FragmentActivity#onResumeFragments() 或者 Activity#onPostResume() 中使用。这两个方法会保证在activity恢复到最初状态后被调用。

commitAllowingStateLoss()只能当做最后的手段
    commit和commitAllowingStateLoss()之间的唯一区别是如果状态丢失后者仅仅是不抛出异常而已。一般情况下你不会想用这个方法因为它仍然会有状态丢失的可能。

由于在百度上看到多数的解决办法是使用commitAllowingStateLoss(),并非说这个办法不行,而是尽量精益求精,找到问题的本质所在。翻译有出入 ,请尽量看原文。
详细的信息请参考原作者文章:http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个错误是因为在 onSaveInstanceState() 方法之后尝试执行某些操作,这是不允许的。 onSaveInstanceState() 方法是在 Activity 即将被销毁之前调用的,它的主要作用是保存 Activity 的状态信息,以便在 Activity 重新创建时恢复状态。因此,在 onSaveInstanceState() 方法之后执行某些操作可能会导致状态信息丢失或不一致。如果需要在 onSaveInstanceState() 方法之后执行某些操作,可以考虑将这些操作放在 onResume() 方法中执行。 ### 回答2: 在Android开发中,当我们的应用程序遇到设备旋转或配置更改等情况时,系统可能会销毁并重建活动,以适应新的设备状态。在这种情况下,在 onSaveInstanceState() 方法中,我们通常将一些重要的应用程序状态保存到 Bundle 对象中,以便在活动重新创建时进行恢复。但是,在 onSaveInstanceState() 方法调用后,一些操作可能会受到限制,因为活动实际上已被销毁。其中包括使用 FragmentTransaction 进行 Fragment 操作,或者提交 AsynTask 等异步操作。如果在此时尝试执行此类操作,则会导致崩溃或其他不可预测的结果。 如果您需要在 onSaveInstanceState() 方法之后执行某些操作,您可以使用简单的技巧来避免出现错误。一种方法是使用 Handler 来执行延迟操作。使用此方法,您可以先在 onSaveInstanceState() 方法中将 Runnable 对象传递给 Handler,并设置合适的延迟时间。当 Runnable 对象在指定时间后在主线程上执行时,Activity 已经重建,所以不存在任何问题。 另一个解决方案是使用 onSaveInstanceState() 方法的一种变体,即 onSaveInstanceState(Bundle, PersistableBundle) 方法。该方法与 onSaveInstanceState(Bundle) 方法不同的是,它还接收一个 PersistableBundle 参数,该参数可以在拥有足够空间的设备上持久化保存。这样,即使活动被销毁并重建,也可以恢复 PersistableBundle 中保存的状态。 总之,在 onSaveInstanceState() 方法被调用后,您应避免执行可能影响 Activity 生命周期的任何操作。如果确实需要执行此类操作,请使用上述技巧来确保正确性和稳定性。 ### 回答3: onSaveInstanceStateAndroid中一个很重要的生命周期方法之一,它通常在Activity或Fragment即将被销毁之前被调用,用于保存Activity或Fragment的状态,以便在Activity或Fragment被重建时恢复它们的状态。在这个方法被调用后,Activity或Fragment的状态已经被保存,如果继续进行操作,可能会导致状态丢失或不一致。 因此,如果在onSaveInstanceState方法被调用后再尝试执行某些操作,就会出现 can not perform this action after onSaveInstanceState 的错误信息。 例如,在Activity的onSaveInstanceState方法被调用后,如果尝试在onPause方法中执行一个Fragment的事务,就会出现这个错误。这是因为在onSaveInstanceState方法被调用后,Fragment的状态已经被保存,并且任何与Fragment相关的操作都不应该被执行,以避免状态丢失或不一致。 为了避免出现can not perform this action after onSaveInstanceState的错误,可以在onSaveInstanceState方法被调用后,避免执行任何与状态相关的操作。如果确实需要在onSaveInstanceState之后执行某些操作,可以考虑使用Handler或post方法进行延迟执行,以确保状态已经被保存并恢复,而不会出现错误。另外,可以尝试使用Fragment的setRetainInstance方法保留Fragment的实例,以避免重建时出现状态丢失的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值