`
椰子面包
  • 浏览: 7162 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

FragmentTransactions 及 Activity State Loss

 
阅读更多

Monkey的时候经常出来

一、

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

    at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1341)

    at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1352)

    at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)

    at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)

 

或者

二、

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

         at android.support.v4.app.FragmentManagerImpl.checkStateLoss(Unknown Source)

         at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(Unknown Source)

         at android.support.v4.app.FragmentActivity.onBackPressed(Unknown Source)

 

  原因分析

    从异常信息:java.lang.IllegalStateException:Can not perform this action after onSaveInstanceState得出是在onSaveInstanceState之后执行了某种不合法的操作导致.

 

onSaveInstanceState之后试图提交FragmentTransaction。为了释放资源,Android系统可以终止非前台Activity所在的进程外的所有应用进程,Activity被回收前系统会回调onSaveInstanceState以保存Activity的状态;在onSaveInstanceState执行之后提交的FragmentTransaction将不会被系统记住,从用户的角度来说FragmentTransaction丢失了,Android为了保证用户体验避免状态的损失,抛出了IllegalStateException

 

建议处理方法

1、在Activity的生命周期方法中提交FragmentTransaction须谨慎。

建议在onCreate()或者#onResumeFragments()onPostResume()中执行,可以保证不会state loss

至于onResume(),因为此时附属于ActivityFragment还没到resume状态,意味着之前的状态有可能还保存着,此时不允许FragmentTransaction修改状态(具体可以参考onResume()方法的注释,及Activity.performResume()的代码)。

 

   2避免异步回调方法里面提交FragmentTransaction

    类似AsyncTask.onPostExecute()或者Handler.handleMessage(),这些方法调用的时候可能Activity.onStop()已被调用,没有一个简单的方法来判断Activity. onSaveInstanceState()是否已被调用(可以考虑自己加个状态变量)。

 

   3假如不在乎state loss使用FragmentTransaction.commitAllowingStateLoss()吧。

    FragmentTransaction.commitAllowingStateLoss()FragmentTransaction.commit()的区别是前者在发生 state loss的时候不会抛出异常。

 

4对于异常二,因为在onSaveInstanceState()之后执行onBackPressed()抛出,这个暂时只在monkey中跑出来过,暂时的解决方法是将onBackPressed()重载,try-catch处理。如有更好的解决方案,请告知,谢谢

         @Override

         public void onBackPressed() {

           try {

                  super.onBackPressed();

                } catch (Exception e) {

                    //一般这里应该把异常信息打印出来

                  finish();

                }

           }

     

 

 

另外说些相关的内容:

Honeycomb(3.0)版本前ActivityonPause()后即可能被杀死,从Honeycomb开始则是在onStop后才可能被杀死。

 

所有版本在onPause()FragmentTransaction.commit()都没有问题;Honeycomb(3.0)之前的版本在onPause()onStop()之间FragmentTransaction.commit()会造成state lossHoneycomb开始在onPause()onStop()之间提交则没有问题;所有版本在onStop()之后FragmentTransaction.commit()都会抛出异常。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics