zoukankan      html  css  js  c++  java
  • Activity与多个fragment的之间的相爱想杀

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

    java.lang.IllegalStateException

    Can not perform this action after onSaveInstanceState

      

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

     

    commitAllowingStateLoss
    
    added 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 >里的

    对象时特别要注意判空。

    如下图:






  • 相关阅读:
    快速获取一个正数的掩码
    使用pdfbox删除pdf指定文字内容
    判断奇偶性
    RabbitMQ高级特性
    常见排序算法
    postman和postman interceptor的安装
    Linux命令
    Chrome 错误代码:ERR_UNSAFE_PORT
    IDEA运行tomcat控制台乱码
    Spring Boot 项目架构
  • 原文地址:https://www.cnblogs.com/zhang-cb/p/7194085.html
Copyright © 2011-2022 走看看