zoukankan      html  css  js  c++  java
  • Fragment already added问题的解决

    问题

    当快速点击切换不同的Fragment的时候部分手机的app竟然挂了,报出了下面的错误 Fragment already added

    java.lang.IllegalStateException: Fragment already added: xxxxFragment

    上网找了很多,大致得到的原因是当快速双击调用FragmentTransaction.add()方法添加fragmentA,而fragmentA不是每次单独生成的,就会引起这个异常。

    上面的内容是网上的解释,不过我认为是因为同一个Fragment被add两次导致的错误,但是奇怪的是我在加载这个Fragment的时候已经做了是否add的判断,为什么还会有这个问题呢。

    private void addFragment(FragmentManager fm, Fragment fragment ) {
            Log.i( "addFragment", "### " + fragment.getId() + "  " + fragment.isAdded() + "  " + fragment.isHidden() );
    
            if (!fragment.isAdded() ) {
                FragmentTransaction ft = fm.beginTransaction();
                fm.executePendingTransactions();
                ft.add( R.id.main_content, fragment );
                ft.commitAllowingStateLoss();
            }

    通过打印结果发现,第一次切换到FragmentA的时候,FragmentA明明已经add了,但是isAdded()依然显示false

    addFragment: ###1 2131755357  false true
    addFragment: ###2 2131755357  false true
    addFragment: ###3 2131755357  false true
    addFragment: ###4 2131755357  false true

    第二次切换到相同FragmentA的时候isAdded()就显示为true了

    addFragment: ###1 2131755357  true true
    addFragment: ###2 2131755357  true true
    addFragment: ###3 2131755357  true true
    addFragment: ###4 2131755357  true true

    在不断快速切换不同的Fragment的时候,isAdded()偶尔会显示false,就因为isAdded()显示了false,那么 ft.add( R.id.main_content, fragment )就会再次执行一次,就会报错,说明通过isAdded()这个方法判断Fragment是否被add可能并不准确。

    方法

    解决方法就是每次add的时候加上一个tag,然后不仅要通过isAdded()判断Fragment是否add,还要通过FragmentManager.findFragmentByTag(tag)获取Fragment,然后判断此Fragment是否为null。

     case R.id.home_tab_a:
            hideAllFragment( fm );
            addFragment( fm, fragmentA, "A" );
            showFragment( fm, fragmentA );
      break;
    
     case R.id.home_tab_b:
            hideAllFragment( fm );
            addFragment( fm, fragmentB, "B" );
            showFragment( fm, fragmentB );
      break;
    
     case R.id.home_tab_c:
            hideAllFragment( fm );
            addFragment( fm, fragmentC, "C" );
            showFragment( fm, fragmentC );
      break;

    影藏所有的Fragment

     private void hideAllFragment(FragmentManager fm) {
            FragmentTransaction ft = fm.beginTransaction();
            if (!shijianFragment.isHidden())
                ft.hide( fragmentA );
    
            if (!riliFragment.isHidden())
                ft.hide( fragmentB );
    
            if (!gongjuFragment.isHidden()) {
                ft.hide( fragmentC );
            }
            ft.commitAllowingStateLoss();
        }

    通过isAdded()判断Fragment是否add,同时通过tag获取Fragment,判断Fragment是否为空,双重判断

       private void addFragment(FragmentManager fm, Fragment fragment, String tag) {
            if (!fragment.isAdded()&&null == fm.findFragmentByTag( tag )) {
                FragmentTransaction ft = fm.beginTransaction();
                fm.executePendingTransactions();
                ft.add( R.id.main_content, fragment, tag );
                ft.commitAllowingStateLoss();
            }
    
        }

    显示Fragment

     private void showFragment(FragmentManager fm, Fragment fragment) {
            FragmentTransaction ft = fm.beginTransaction();
            ft.show( fragment );
            ft.commitAllowingStateLoss();
        }
  • 相关阅读:
    CodeSmith入门教程
    AJAX调用实例
    药品监控增加表结构
    典型SQL 语句总结
    CRM中常用代码
    win2000sever+IIS5不能下载exe文件处理方法
    常用的文件对应的MIME类型
    数据库范式1NF 2NF 3NF BCNF
    多线程编程中如何更改UI值
    NHibernate学习笔记(2)—关系映射
  • 原文地址:https://www.cnblogs.com/yelanggu/p/10970305.html
Copyright © 2011-2022 走看看