DialogFragment异常Fragment already added的原因与解决办法

摘要:
碎片mDetached){if{thrownewIllegalStateException;}已同步{this.mAdded.add;}fragment.mAdded=true;…}}DialogFragment异常的解决方案是知道异常的原因是“show方法已被多次执行,并且添加了多个连续的add事务”。然后重写show方法,使添加事务不连续,并在每次添加之前删除原始事务。

DialogFragment异常的表现形式
快速多次点击按钮展示DialogFragment弹框,100%复现崩溃

java.lang.IllegalStateException: Fragment already added: XXDialogFragment

DialogFragment异常的发生原因

查看DialogFragment的show方法源码,发现每次show的时候都会提交一个add fragment的事务。

DialogFragment.java

public void show(FragmentManager manager, String tag) {
    this.mDismissed = false;
    this.mShownByMe = true;
    FragmentTransaction ft = manager.beginTransaction();
    ft.add(this, tag);
    ft.commit();
}

当快速多次点击按钮时,短时间内调用多次show方法,添加多个add事务(add事务A、add事务B等)。然后系统在执行事务队列时,在执行了addFragment后,发现又要add这个Fragment,即抛出异常:

FragmentManagerImpl.java

public void addFragment(Fragment fragment, boolean moveToStateNow) {
    if (DEBUG) {
        Log.v("FragmentManager", "add: " + fragment);
    }

    this.makeActive(fragment);
    if (!fragment.mDetached) {
        if (this.mAdded.contains(fragment)) {
            throw new IllegalStateException("Fragment already added: " + fragment);
        }

        synchronized(this.mAdded) {
            this.mAdded.add(fragment);
        }

        fragment.mAdded = true;
        ...
    }

}

DialogFragment异常的解决办法

既然知道异常的原因是“执行了多次show方法,添加了多个连续的add事务”。那就改写下show方法,让add事务不连续,每次add之前都把原来的remove掉。解决代码如下:

public class ActivityDialogFragment extends DialogFragment {
    
    @Override
    public void show(FragmentManager manager, String tag) {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
            if (manager.isDestroyed())
                return;
        }
        try {
            //在每个add事务前增加一个remove事务,防止连续的add
            manager.beginTransaction().remove(this).commit();
            super.show(manager, tag);
        } catch (Exception e) {
            //同一实例使用不同的tag会异常,这里捕获一下
            e.printStackTrace();
        }
    }
}

免责声明:文章转载自《DialogFragment异常Fragment already added的原因与解决办法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Flutter 实现 3des 加密DB2_SQL_常用知识点&实践下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

.NET Core分布式事件总线、分布式事务解决方案:CAP

简介 CAP 是一个遵循 .NET Standard 标准库的C#库,用来处理分布式事务以及提供EventBus的功能,它具有轻量级,高性能,易使用等特点。 分布式事务是在分布式系统中不可避免的一个硬性需求,CAP 没有采用两阶段提交(2PC)这种事务机制,而是采用的 本地消息表+MQ 这种经典的实现方式,这种方式又叫做 异步确保。 CAP 实现了 Eve...

分布式一致性协议之2PC与3PC

上文提到过数据库中2PC如何实现的,今天就来好好画画2PC与3PC的流程图,以及对比它们之间的关系和区别。 分布式事务是为了解决微服务架构(形式都是分布式系统)中不同节点之间的数据一致性问题。这个一致性问题本质上解决的也是传统事务需要解决的问题,即一个请求在多个微服务调用链中,所有服务的数据处理要么全部成功,要么全部回滚。当然分布式事务问题的形式可能与传统...

美团点评面试20190515

1. 自我介绍 2. 项目介绍,项目难点 3. 笔试题研究过吗? 4. Mybatis多参数传递    //方法1:顺序(索引)传参法 public User selectUser(String name, int deptId); <select resultMap="UserResultMap"> select * fro...

跨时代的分布式数据库 – 阿里云DRDS详解

随着互联网时代的到来,计算机要管理的数据量成指数级别的飞速上涨。而我们完全无法对用户数做出准确的预估,我们的系统所需要支持的用户数很可能在短短的一个月内突然爆发式的增长几千倍,数据也很可能快速的从原来的几百GB飞速上涨到了几百个TB。如果在这爆发的关键时刻,系统不稳定或无法访问,那么对于业务将会是毁灭性的打击。 伴随着这种对于系统性能、成本以及扩展性的新需...

【--RocketMQ--】RocketMQ实现事务消息

在RocketMQ4.3.0版本后,开放了事务消息这一特性,对于分布式事务而言,最常说的还是二阶段提交协议,那么RocketMQ的事务消息又是怎么一回事呢,这里主要带着以下几个问题来探究一下RocketMQ的事务消息:   事务消息是如何实现的  我们有哪些手段来监控事务消息的状态  事务消息的异常恢复机制  RocketMQ的事务消息是如何实现的 Roc...

《转》事务对数据库的重要性

所谓事务是用户定义的一个操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位。   事务的开始与结束可以由用户显式控制。如果用户没有显式地定义事务,则由DBMS按缺省规定自动划分事务。在SQL语言中,定义事务的语句有三条:    BEGIN TRANSACTION    COMMIT    ROLLBACK   事务通常是以BEGIN TRAN...