问题

当快速点击切换不同的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();
}

Fragment already added问题的解决的更多相关文章

  1. viewpager和fragment预加载的解决

    在使用Viewpager和fragment处理中会出现预加载的问题,最近看别人的代码,终于找到了一个很好的处理方法 能有效的解决预加载的问题,在fragment都继承一个重写setUserVisibl ...

  2. Activity has leaked window that was originally added(以解决)

     在编写Android程序的时候,遇到一个隐藏性问题.仔细查看LogCat,错误信息如下: 10-31 13:03:34.549: ERROR/WindowManager(444): Activi ...

  3. Android 关于Fragment重叠问题分析和解决

    一.问题描述 相信大家在使用Fragment的过程中,肯定碰到过Fragment重叠的问题,重启应用就好了.然而原因是什么呢? 二.原因分析 首先,Android管理Fragment有两种方式,使用a ...

  4. 多个fragment中重叠问题的解决方法

    这个方法适用性有限. 我的是一个mainActivity,然后下部四个按钮,点击时先隐藏所有的fragment,然后再new一个新的出来,如果存在,则直接显示出来,看上去一切都没有问题. 但是通过fr ...

  5. fragment没有getWindowManager 关于fragment下的报错解决方法

    其实很简单:只需要在getWindowManager().getDefaultDisplay().getMetrics(metric) 前面加上getactivity()即可.

  6. Fragment已经被added了导致的异常。

    java.lang.IllegalStateException: Fragment already added:  ******Effect 出现的原因是commit方法提交是异步的,所以容易出现,判 ...

  7. 【转】解决Fragment already active方法

    http://blog.csdn.net/u011730649/article/details/43227721 今天在项目中使用Fragment的时候出现这样的错误: 01-28 10:53:34. ...

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

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

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

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

随机推荐

  1. docker 进程 转载:https://www.cnblogs.com/ilinuxer/p/6188303.html

    今天我们会分析Docker中进程管理的一些细节,并介绍一些常见问题的解决方法和注意事项. 容器的PID namespace(名空间) 在Docker中,进程管理的基础就是Linux内核中的PID名空间 ...

  2. Greenplum 添加mirror步骤

    原文链接:https://yq.aliyun.com/articles/695864 [TOC] 概述 新安装的greenplum集群只有primary节点,没有mirror.高可用性没得到保证.所以 ...

  3. ES code study

    pom.xml <?xml version="1.0" encoding="UTF-8"?><project xmlns="http ...

  4. Java 基础:单例模式 Singleton Pattern

    1.简介 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单一的类,该类负责创 ...

  5. Docker 常用命令,自用,持续更

    1.进入容器 docker exec -it 容器id /bin/bash docker exec -it db30f533ee1b /bin/bash 2.复制文件到容器 docker cp 文件路 ...

  6. 我为什么选择Vim

    总看到一些飞快敲击键盘而不用鼠标的时候你可以很羡慕和佩服,其实这完全没有必要.就像一个吉他手熟练地弹吉他有必要羡慕吗?一个瓦匠熟练地砌砖有必要羡慕吗?这些都是他们赖以生存的工具而已,熟练地运用工具是理 ...

  7. vxlan和macvlan操作

    vxlan: 192.168.1.112 ———— 192.168.1.108 —— 192.168.1.109192.168.1.112配置:docker run -d -p 8500:8500 - ...

  8. 沸腾换热UDF【转载】

    #include "udf.h"    //包括常规宏 #include "sg_mphase.h"    // 包括体积分数宏 CVOF(C,T) #defi ...

  9. python中普通函数调用协程

    import asyncio def target(loop, timeout=None): future = asyncio.run_coroutine_threadsafe(add(1, b=2) ...

  10. ActiveMq 本地安装及启动(Windows)

    首先下载MQ的安装包 http://activemq.apache.org/download.html 1.点击最新版本的ActiveMQ的 2.这里有窗户版本和Linux的的版本,这里我们选择窗口版 ...