踩到这个矿坑:同一个activity管理多个fragment的时候遇到下面的异常

java.lang.IllegalStateException

Can not perform this action after onSaveInstanceState

  官方文档说明:http://developer.android.com/reference/android/app/FragmentTransaction.html#commitAllowingStateLoss()

 

commitAllowingStateLossadded in API level 11
int commitAllowingStateLoss ()
Like commit() but allows the commit to be executed after an activity's state is saved. This is dangerous because the commit can be lost if the activity needs to later be restored from its state, so this should only be used for cases where it is okay for the UI state to change unexpectedly on the user.

大家都知道Activity的执行destory()方法之前会先执行一个方法onSaveInstanceState(),这个方法就是保存activity在销毁之前保存临时数据的,以此来防止数据丢失。

那么也就是说onSaveInstanceState()执行之后你还要执行commit()就会报上面的错。

通俗的说就像你去赶动车一样,都已经停止检票了,你还一直在刷票机上一直刷,肯定是刷不过的啊,此时肯定要寻求其他的解决办法。

那么解决办法就是把commit()方法替换成commitAllowingStateLoss()就ok。

下面贴出来腾讯bugly平台为我们整理的解决方案,不得不说大平台人才多,技术6

#2875 java.lang.IllegalStateException
Can not perform this action after onSaveInstanceState解决方案
状态异常。
java.lang.IllegalStateException异常产生的原因及解决办法  错误类型大致为以下几种:
java.lang.IllegalStateException:Cannot   forward   a   response   that   is   already   committed
IllegalStateException:response already commited
IllegalStateException:getOutputStream() has already been called for this request
…………
=========================================================
IllegalStateException: Can not perform this action after onSaveInstanceState:
#解决办法:onSaveInstanceState方法是在该Activity即将被销毁前调用,来保存Activity数据的,如果在保存玩状态后
再给它添加Fragment就会出错。解决办法就是把commit()方法替换成 commitAllowingStateLoss()
=========================================================
错误原因:该异常表示,当前对客户端的响应已经结束,不能在响应已经结束(或说消亡)后再向客户端(实际上是缓冲区)输出任何内容。Object is no longer valid to operate on. Was it deleted by another thread?该异常表示,realmObject对象在其他线程已被删除,在这个线程中使用的时候抛出的异常。具体分析:首先解释下flush(),我们知道在使用读写流的时候数据先被读入内存这个缓冲区中, 然后再写入文件,但是当数据读完时不代表数据已经写入文件完毕,因为可能还有一部分仍未写入文件而留在内存中,这时调用flush()方法就会把缓冲区的数据强行清空输出,因此flush()的作用就是保证缓存清空输出。response是服务端对客户端请求的一个响应,其中封装了响应头、状态码、内容等,服务端在把response提交到客户端之前,会向缓冲区内写入响应头和状态码,然后将所有内容flush。这就标志着该次响应已经committed(提交)。对于当前页面中已经committed(提交)的response,就不能再使用这个response向缓冲区写任何东西(注:同一个页面中的response.XXX()是同一个response的不同方法,只要其中一个已经导致了committed,那么其它类似方式的调用都会导致 IllegalStateException异常)。
参考:http://my.oschina.net/guhai2004/blog/187041,https://github.com/realm/realm-java/issues/1206

补充另一种异常情况:
我这里的异常是:
java.lang.IllegalStateException
Can't change tag of fragment d{e183845 #0 d{e183845}}: was d{e183845} now d{e183845 #0 d{e183845}}
经查,我在显示fragment的代码中使用了:
fragment.show(getSupportFragmentManager, fragment.toString());
而这里是因为两次toString()结果不同,导致不同的tag指向的是同一个fragment。
获取fragment的tag的正确方法应该是使用其提供的fragment.getTag()方法。=====================================================
补充异常:
java.lang.IllegalStateException
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 37 path $.data
错误原因:该异常是由于服务器错误返回的JSON字符串和服务器正常下时返回的JSON字符串结构不同,导致利用Gson解析的时候报了一个异常:本该去解析集合却强制去解析对象所致.
解决办法:在使用Gson解析JSON时try cash一下,不报错按照正常逻辑继续解析,报异常则处理为请求失败逻辑即可.
======================================================

Fragment弹出回退栈的方法

void popBackStack()

弹出堆栈中的一个并且显示,类似按下返回键的操作;

popBackStack(String tag,int flags)

  • tag可以为null或者相对应的tag,flags只有0和1(POP_BACK_STACK_INCLUSIVE)两种情况

  • 如果tag为null,flags为0时,弹出回退栈中最上层的那个fragment。

  • 如果tag为null ,flags为1时,弹出回退栈中所有fragment。

  • 如果tag不为null,那就会找到这个tag所对应的fragment,flags为0时,弹出该

    fragment以上的Fragment,如果是1,弹出该fragment(包括该fragment)以

    上的fragment。


popBackStack(int id,int flags)

  • 与popBackStack(String tag,int flags)类似,找到id代表的fragment,然后执行一样的操作

popBackStackImmediate(int id, int flags)

popBackStackImmediate(String name, int flags)

popBackStackImmediate()

这几个方法类似以上的方法,只不过这几个在内部调用时会立即弹出

很多时候我们都以为fragment入栈后,譬如 依次入栈 fragment A ,B ,C ,D,

然后弹出B fragment,在回退栈里并不是我们想象的只剩下 D C A ,而是D C null

A,所以使用FragmentManager.getFragments(),然后拿List< Fragment >里的

对象时特别要注意判空。

如下图:

转载于:https://www.cnblogs.com/zhang-cb/p/7194085.html

Activity与多个fragment的之间的相爱想杀相关推荐

  1. react 遍历对象_React 和 Vue 之间的相爱相杀

    React 和 Vue 应该是国内当下最火热的前端框架,当然 Angular 也是一个不错的框架,但是这个产品国内使用的人很少再加上我对 Angular 也不怎么熟悉,所以就不在这篇文章中做对比了. ...

  2. 司马懿和诸葛亮之间的相爱相杀

    阅读本文大概需要2分钟 良好的习惯需要不断慢慢培养.我现在基本每天晚上的轨迹是这样的:每天晚上下班后,洗漱完基本就到晚上七点半左右了. 19:30-21:00   看电视剧. 21:00-21:30 ...

  3. 30年「相爱相杀」 :30张照片回顾乔布斯和比尔盖茨之间「不得不说」的故事

    Python实战社群 Java实战社群 长按识别下方二维码,按需求添加 扫码关注添加客服 进Python社群▲ 扫码关注添加客服 进Java社群▲ 来源丨BI 来源公众号丨新智元(ID:AI_era) ...

  4. 30年「相爱相杀」 :30张照片回顾乔布斯和比尔盖茨之间「不得不说」的故事...

    Python实战社群 Java实战社群 长按识别下方二维码,按需求添加 扫码关注添加客服 进Python社群▲ 扫码关注添加客服 进Java社群▲ 来源丨BI 来源公众号丨新智元(ID:AI_era) ...

  5. android4.4 fragment,在Activity和多个Fragment之间共享资源

    在Activity和多个Fragment之间共享资源 Android Studio 默认生成的代码一般是这样的: package com.messy.lingplayer.playui import ...

  6. Activity跳转到Fragment

    当Activity跳转到Fragment 把他当做两个Activity来跳转 首先 我们来复习一下两个页面之间的传值跳转 页面一 OneActivity Intent intent = new Int ...

  7. android 多个fragment切换,一个Activity中多个Fragment的切换

    经常会遇到在一个activity界面上布局多个fragment,但是如何从一个fragment跳转到另一个fragment呢?今天在做项目中恰好遇到这样的问题,点击首页fragment的更多店铺,会切 ...

  8. Activity 数据传递给Fragment

    下面说的宿主Activity 里面的Fragment 加入现在Fragment 里面 想使用Activity 里面的城市id 方法 1 使用set值 在Fragment 里面写一个set方法 在act ...

  9. 什么时候用activity什么时候用fragment

    转载请标明出处:  http://blog.csdn.net/michael1112/article/details/58257035 江东橘子的博客 1. 当你有一个activity,想让这个act ...

最新文章

  1. 简易排水简车的制作 TurnipBit 系列教程
  2. 从构造函数看java.io
  3. 远程连接Windows服务器
  4. 破解xp(sp2)密码
  5. C语言520心形表白,初学者福利!!
  6. 422器件与lvds接收器的区别_SPI、I2C、UART三种串行总线的原理、区别
  7. pytorch神经网络因素预测_实战:使用PyTorch构建神经网络进行房价预测
  8. python导入不在同一路径的函数_Python小课堂|模块
  9. 中兴助力软银开启首次5G测试
  10. ios下使用speex进行音频压缩
  11. 开源主流分布式文件系统简单介绍
  12. 常见信息安全威胁与经典案例
  13. 物联网产品的平台架构
  14. 基于R的飞机航线数据可视化(卫星地图)
  15. 移动互联网技术(wifi)
  16. Wine-Staging 5.6 修补游戏补丁
  17. 英特尔 QSV 在 FFMPEG 中的使用(Linux)
  18. Excel数据透视表、数据透视图
  19. 用python和sympy库解决方程组问题_使用 Python 解数学方程
  20. 每日一犬 · 中国冠毛犬

热门文章

  1. Head First JSP---随笔二
  2. zcmu-2149(归并排序)
  3. 大数运算(5)——大数除法(取模、取余)
  4. How to Build Your Own Blockchain Part 4.2 — Ethereum Proof of Work Difficulty Explained
  5. 带你全面了解比特黄金(bitcoin gold)分叉
  6. Android系统启动-init篇
  7. 美团Android DEX自动拆包及动态加载简介
  8. ARM64的启动过程之(三):为打开MMU而进行的CPU初始化
  9. ARM64的启动过程之(二):创建启动阶段的页表
  10. 安装mysql5.7