Can not perform this action after onSaveInstanceState

 

http://zhiweiofli.iteye.com/blog/1539467

 

首先得了解一下我那项目的一些基本情况,UI结构是TabActivity包含着5个Tabs,每个tab又是一个独立的Activity。

异常是发生在android 4.03系统上,当我在某个Tab上按Back键时,就会报出java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

从logout里发现了整个异常发生的过程:

 

Java代码  收藏代码
  1. java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
  2. at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1109)
  3. at android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:399)
  4. at android.app.Activity.onBackPressed(Activity.java:2066)
  5. at android.app.Activity.onKeyUp(Activity.java:2044)
  6. at android.view.KeyEvent.dispatch(KeyEvent.java:2529)
  7. at android.app.Activity.dispatchKeyEvent(Activity.java:2274)
  8. at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1803)
  9. at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
  10. at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
  11. at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
  12. at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1855)
  13. at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1277)
  14. at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
  15. at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1803)
  16. at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
  17. at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
  18. at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
  19. at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
  20. at android.widget.TabHost.dispatchKeyEvent(TabHost.java:297)
  21. at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
  22. at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
  23. at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
  24. at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1855)
  25. at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1277)
  26. at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
  27. at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1803)
  28. at android.view.ViewRoot.deliverKeyEventPostIme(ViewRoot.java:2880)
  29. at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2853)
  30. at android.view.ViewRoot.handleMessage(ViewRoot.java:2028)
  31. at android.os.Handler.dispatchMessage(Handler.java:99)
  32. at android.os.Looper.loop(Looper.java:132)
  33. at android.app.ActivityThread.main(ActivityThread.java:4028)
  34. at java.lang.reflect.Method.invokeNative(Native Method)
  35. at java.lang.reflect.Method.invoke(Method.java:491)
  36. at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
  37. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
  38. at dalvik.system.NativeStart.main(Native Method)

上面的异常信息表示,我写的类不是异常的源头。根据异常信息Can not perform this action after onSaveInstanceState,可以了解到异常原因:在onSaveInstanceState行为之后,app执行某个不能响应的行为而导致 异常发生。

在信息at android.app.Activity.onBackPressed(Activity.java:2066),这一句表明异常是在响应返回键响应事件的行为上发生的。我们顺藤摸瓜,考究一下在我们按下返回键时,activity会执行的响应:onKeyDown–>onBackPressed–>onPause->onStop->onDestroy。

那导火索onSaveInstanceState又是在什么时候执行的?

我们先看android API的一段原文:

 

Java代码  收藏代码
  1. 先看Application Fundamentals上的一段话:
  2.       Android calls onSaveInstanceState() before the activity becomes vulnerable to being destroyed by the system, but does not bother calling it when the instance is actually being destroyed by a user action
  3. (such as pressing the BACK key)

 

从上面可以知道,当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。

注意上面的双引号,何为“容易”?言下之意就是该activity还没有被销毁,而仅仅是一种可能性。

onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据。

那为什么项目里头响应onBackPressed事件时会报出上面的异常呢,还表明是after onSaveInstanceState?

原因是我Tab里面的Activity响应了onBackPressed事件,得弹出task,作为它的父容器TabActivity当然也得弹出task,TabActivity 变得“容易”被系统销毁,于是就调用onSaveInstanceState保存状态。

现在整个流程都明白了,可是,这一切都很正常啊,这个流程也很符合Activity的生命周期啊,为什么还会报异常呢?还是在最新的android 4.03上出问题,难道是说,系统不兼容?

对!

经过一番网上查阅,发现API 11 以上某些控件,包括 Fragment还有ActivityGroup,在调用saveInstanceState存在Bug,可能是google对saveInstanceState的实现做过修改。

直到隐藏在后面的原因,解决问题的思路就出来了:让父容器TabActivity在不调用saveInstanceState的情况下onDestroy

具体思路在tab上面的activity监听BACK键的事件,响应并拦截,再通过广播方式通知父容器TabActivity,主动销毁自己,达到原来响应onBackPressed退出App的效果。

 

 

1
0
分享到:
评论

13 楼 wyyl1 2015-11-12
大致意思是说我使用的 commit方法是在Activity的onSaveInstanceState()之后调用的,这样会出错,因为onSaveInstanceState
方法是在该Activity即将被销毁前调用,来保存Activity数据的,如果在保存玩状态后再给它添加Fragment就会出错。解决办法就
是把commit()方法替换成 commitAllowingStateLoss()就行了,其效果是一样的。

原文地址:http://blog.csdn.net/ranxiedao/article/details/8214936

12 楼 IT之冕 2015-09-01
我的方法是注释掉super.onBackPressed(),加上finish()
@Override
public void onBackPressed() {
//      super.onBackPressed();
finish();
}
11 楼 wqbs369 2015-06-17
我的做法是在 fragment 的onDestroyView 方法中判断
if(!getActivity.isFinishing()){
屏蔽..到之前的.将当前的fragment从此fragment去除
getAcitivity().getSupportFramgnetManager.beginTransaction.remove(view).commit();
}
//view 为onCreateView中 inflate的view
10 楼 AlexTech 2014-08-30
谢谢,解决了我大问题
9 楼 Tao_taobujue 2014-04-29
lhy046510 写道
lz可以给个列子吗?谢谢
8 楼 芦茨法 2013-12-17
芦茨法 写道
我也有碰到这个问题,我的解决方案是在父容器Activity与了Activity里加了个‘onSaveInstanceState()’方法内未加内容。可以解决问题

补充:‘子’Activity不是‘了’Activity

7 楼 芦茨法 2013-12-17
我也有碰到这个问题,我的解决方案是在父容器Activity与了Activity里加了个‘onSaveInstanceState()’方法内未加内容。可以解决问题
6 楼 zhiweiofli 2013-05-06
pengqinping 写道
你这样是解决了按back,要是按Home和程序突然打断,会不会也有这种情况?

也不一定,saveInstanceState由系统控制着,系统觉得需要,还是会去调用的

5 楼 pengqinping 2013-04-27
你这样是解决了按back,要是按Home和程序突然打断,会不会也有这种情况?
4 楼 zhiweiofli 2012-06-12
lhy046510 写道
让父容器TabActivity在不调用saveInstanceState的情况下onDestroy
想实现这样的功能,有列子吗?lhy046510@163.com,感谢!

重写各个tabview的onBackPressed,拦截Back键的事件,在里面直接调finish,然后通知父容器tabActivity执行finish,就可避开saveInstanceState的调用,试试吧

3 楼 lhy046510 2012-06-11
让父容器TabActivity在不调用saveInstanceState的情况下onDestroy
想实现这样的功能,有列子吗?lhy046510@163.com,感谢!

2 楼 zhiweiofli 2012-06-08
lhy046510 写道
lz可以给个列子吗?谢谢

你需要怎样的例子呢?

1 楼 lhy046510 2012-06-07
lz可以给个列子吗?谢谢