在使用Fragment的过程中,常常会遇到在Activity的onSaveInstanceState方法调用之后,操作commit或者popBackStack而导致的crash.
因为在onSaveInstanceState方法之后的操作状态可能会丢失,因此Android framework默认会抛出一个异常.
对于commit方法来说,单纯避免这个异常很简单,使用commitAllowingStateLoss方法即可.但是popBackStack以及
popBackStackImmediate也都会检查state(checkStateLoss),特别需要注意的是Activity的
onBackPressed方法

如果onBackPressed在onSavedInstanceState之后调用,那么就会crash.

onBackPressed的调用时机:

* targetSdkVersion <= 5,在onKeyDown中调用
* targetSdkVersion > 5,在onKeyUp中调用
onSavedInstanceState的调用时机(如果调用的话):

* 一定在onStop之前
* 可能在onPause之前,也可能在onPause与onStop之间
需要注意的是: onSavedInstanceState方法不一定会调用,只有在Activity因为某些原因而被Framework销毁,并且之后还需要重新创建的情况,才需要调用(例如:旋屏,或者内存不足而回收返回栈中的某些Activity)

举例:
* Activity A在前台时,屏幕逐渐变暗直至锁屏,那么A的onSavedInstanceState会被调用
* Activity A start Activity B,Activity A的onSavedInstanceState会被调用
* Activity A因为返回键或者finish调用而返回到上一个界面,那么A的onSavedInstanceState不会被调用
因此,当onBackPressed在onSavedInstanceState方法之后调用,就一定会crash.解决方法主要有两种:

重写Activity的onSavedInstanceState()方法,并且注释掉super调用.
这种方法能避免crash,但是它会导致整个Activity的状态丢失.以DialogFragment为例,正常情况下,显示的
DialogFragment在旋屏Activity重新创建之后,不需要我们处理,Dialog会自动显示出来(参见
DialogFragment.onStart()),但是注释掉Activity的onSavedInstanceState()方法之
后,Fragment状态丢失,Activity重新创建之后,Dialog也就不会再显示出来了.

更好且通用的做法:在调用commit,popBackStack以及onBackPressed方法之前,判断
onSavedInstanceState()方法是否已经执行,并且onResume方法还没有执行,如果不是,那么直接操作,否则加入到
pending队列,等待onResumeFragments或者onPostResume之后再执行.

注意:不要在onResume中操作,因为这时候FragmentManager中的mStateSaved依然可能是true.(如果执行顺序是
onSavedInstanceState()->onPause()->onResume() 或者
onPause()->onSavedInstanceState()->onResume());

public void endPaintingPager(int index) {
if (mFirstLevel == PAINTING_PAGER) {
mFirstLevel = PAINTER_START;
if (!mIsStateSaved) {
getSupportFragmentManager().popBackStack();
} else {
mPopBackStackRunnable = new Runnable() {
@Override
public void run() {
getSupportFragmentManager().popBackStack();
}
};
}
}
}
@Override
protected void onPostResume() {
super.onPostResume();
if (mPopBackStackRunnable != null) {
mPopBackStackRunnable.run();
}
}

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState的更多相关文章

  1. java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState问题解决

    (1)我用的是fragment,在onStop但是没有onDestroy的情况下切换(replace)fragment时报 java.lang.IllegalStateException: Can n ...

  2. java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState解决?

    做项目到最后整合的时候测试的时候发现  切换tab更换fragment的时候抛出了这个异常,根据异常信息Can not perform this action after onSaveInstance ...

  3. 解决IllegalStateException: Can not perform this action after onSaveInstanceState

    今天使用Fragment的时候,出现了这个错误 IllegalStateException: Can not perform this action after onSaveInstanceState ...

  4. 【转】 解决IllegalStateException: Can not perform this action after onSaveInstanceState

    今天使用Fragment的时候,出现了这个错误 IllegalStateException: Can not perform this action after onSaveInstanceState ...

  5. 解决IllegalStateException: Can not perform this action after onSaveInstanceState:

    今天做项目中的支付宝功能,是在fragment中做的,在支付成功后,想切换到支付成功的页面. 结果就报错了IllegalStateException: Can not perform this act ...

  6. IllegalStateException: Can not perform this action after onSaveInstanceState

    http://www.cnblogs.com/zgz345/archive/2013/03/04/2942553.html 今天使用Fragment的时候,出现了这个错误 IllegalStateEx ...

  7. Android 错误:IllegalStateException: Can not perform this action after onSaveInstanceState

    今天做Fragment切换.状态保存功能的时候,出现了这个错误: E/AndroidRuntime(12747): Caused by: java.lang.IllegalStateException ...

  8. [Android Pro] java.lang.IllegalStateException: Fragment(XXFragment) not attached to Activity异常

    转载:http://blog.csdn.net/winson_jason/article/details/20357435 下边两个问题,是在开发中碰到的一些关于Fragment的偶发性的问题,今天时 ...

  9. Can not perform this action after onSaveInstanceState

    java.lang.RuntimeException: Unable to resume activity {com.tongyan.nanjing.subway/com.tongyan.struct ...

随机推荐

  1. C 语言字符串(译)

    C 语言的 switch 语句非常强大.然而,它不能用字符串作为判断条件,只能用常整数.这是可以理解的,因为 C 的字符串仅仅是数组,它们并不是并不是一个整体. 在某些情况下,将 string 作为 ...

  2. bzoj1179

    这种tarjan+dp的水题我竟然还WA了两次,要小心! type link=^node;      node=record        po:longint;        next:link; ...

  3. leetcode reverse integer&&Palindrome Number

    public class Solution { public int reverse(int x) { int ret=0; while(x!=0) { int t=x%10; ret=ret*10+ ...

  4. JavaScript高级程序设计34.pdf

    元素大小 偏移量 offsetHeight:元素在垂直空间上占用的大小,以像素计.包括元素的高度.(可见的)水平滚动条的高度.上边框高度和下边框高度. offsetWidth:元素在水平空间上占用的大 ...

  5. Bzoj 3343: 教主的魔法 分块,二分

    3343: 教主的魔法 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 821  Solved: 364[Submit][Status][Discuss ...

  6. linux 多线程基础3

    一.线程属性 线程具有属性,用pthread_attr_t表示,在对该结构进行处理之前必须进行初始化,在使用后需要对其去除初始化.我们用pthread_attr_init函数对其初始化,用pthrea ...

  7. c语音中打印参数调用层级即call stack, call trace

    http://stackoverflow.com/questions/105659/how-can-one-grab-a-stack-trace-in-c There's backtrace(), a ...

  8. Get familiar with key Frameworks of ios

    Frameworks make your life easier as an iOS Developer. They allow you to reuse code written by other ...

  9. yum puppet

    config.gem: Unpacked gem factory_girl-1.3.3 in vendor/gems has no specification file. Run 'rake gems ...

  10. 学习:Linux基础知识<一>

    >>硬盘分区模式 硬盘分区模式一般如下: -- /  (根目录) -- /usr    (操作系统) --/home (用户信息) -- /var    (默认服务器的登录文件,邮件与WW ...