android DialogFragment 的show()的问

2020-04-24  本文已影响0人  木木禾木

在使用DialogFragment的show时,会发生一些异常,整理一下。

1、重复添加的异常

java.lang.IllegalStateException: Fragment already added

2、状态相关的异常

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState


带着问题来看看DialogFragment源码中的show做了什么:

    /**
     * Display the dialog, adding the fragment to the given FragmentManager.  This
     * is a convenience for explicitly creating a transaction, adding the
     * fragment to it with the given tag, and committing it.  This does
     * <em>not</em> add the transaction to the back stack.  When the fragment
     * is dismissed, a new transaction will be executed to remove it from
     * the activity.
     * @param manager The FragmentManager this fragment will be added to.
     * @param tag The tag for this fragment, as per
     * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}.
     */
    public void show(FragmentManager manager, String tag) {
        mDismissed = false;
        mShownByMe = true;
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, tag);
        ft.commit();
    }

源码中的show方法很简单,所以原因也很明显:

  1. 由于直接使用 FragmentTransaction 的 add() 方法,所以会出现重复添加;
  2. 由于使用的是 FragmentTransaction 的 commit() ,而不是 commitAllowingStateLoss() ,所以会出现状态问题的异常。(之前记得有分析过commit与commitAllowingStateLoss的区别 android Fragment的commit与commitAllowingStateLoss

问题修复

重写DialogFragment的show(),如下:

    @Override
    public void show(FragmentManager manager, String tag) {
        //避免重复添加的异常 java.lang.IllegalStateException: Fragment already added
        Fragment fragment = manager.findFragmentByTag(tag);
        if (fragment != null) {
            FragmentTransaction fragmentTransaction = manager.beginTransaction();
            fragmentTransaction.remove(fragment);
            fragmentTransaction.commitAllowingStateLoss();
        }
        //避免状态丢失的异常 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
        try {
            super.show(manager, tag);
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }

当然也可以通过反射来调用 commitAllowingStateLoss(),只是复杂度比较高,不是很必要。

关闭DialogFragment也要尽量使用dismissAllowingStateLoss() 而不是 dismiss() 额~


上一篇下一篇

猜你喜欢

热点阅读