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


    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();
            }
        }
    }
  • 相关阅读:
    Fast polling using C, memcached, nginx and libevent
    为什么MongoDB可以替代MySQL?
    comet server 的介绍及方案选型
    多任务服务器架构设计
    基于libev面向分布式数据系统的C10K服务器设计
    libev & libevent简介
    memcached、redis、mysql、mongodb结合架构数据库系统
    删除数组中的重复元素
    不用运算符比较两个int数的大小
    JDBC之简介
  • 原文地址:https://www.cnblogs.com/ganzhijie/p/14249580.html
Copyright © 2020-2023  润新知