高级UI

DialogFragment 使用遇到的坑

2020-06-29  本文已影响0人  怎么快乐

坑一

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
        at androidx.fragment.app.FragmentManagerImpl.checkStateLoss(FragmentManagerImpl.java:1536)
        at androidx.fragment.app.FragmentManagerImpl.enqueueAction(FragmentManagerImpl.java:1558)
        at androidx.fragment.app.BackStackRecord.commitInternal(BackStackRecord.java:317)
        at androidx.fragment.app.BackStackRecord.commit(BackStackRecord.java:282)
        at androidx.fragment.app.DialogFragment.show(DialogFragment.java:155)

出现这个错误是因为 在Activity的onSaveInstanceState方法调用之后,操作commit方法。
使用场景模拟:已版本升级功能为例。进入首页Activity,会去请求检测版本升级接口,接口还没请求成功时,我们按Home键退出Activity回到桌面,接口请求成功后,需要弹出升级弹框,此时调用DialogFragment的show方法就会报上面的错。

解决办法,重写show方法,代码如下:

public void show(@NonNull FragmentManager manager) {
        try {
            Class<?> c = Class.forName("androidx.fragment.app.DialogFragment");
            Field dismissed = c.getDeclaredField("mDismissed");
            dismissed.setAccessible(true);
            dismissed.set(this, false);
            Field shownByMe = c.getDeclaredField("mShownByMe");
            shownByMe.setAccessible(true);
            shownByMe.set(this, true);
            FragmentTransaction fragmentTransaction = manager.beginTransaction();
            fragmentTransaction.add(this, getFragmentTag());
            fragmentTransaction.commitAllowingStateLoss();
            if (onShowDismissListener != null) onShowDismissListener.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
//通过反射修改mDismissed、mShownByMe两个变量的值是因为,源码中show方法会修改这两个值

坑二

 java.lang.IllegalStateException: Fragment already added: MyDialogFragment{bfb3730 (d53ee214-34c1-49ff-9c4b-fac59aeb9df3) myDialogFragment}
        at androidx.fragment.app.FragmentManagerImpl.addFragment(FragmentManagerImpl.java:1379)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:399)
        at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
        at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:224)
        at android.app.ActivityThread.main(ActivityThread.java:7551)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

出现这个错误是因为 同一个Fragment被add两次导致的错误
使用场景模拟:快速点击按钮,弹出分享弹框,有时候会因为手机卡顿,导致可以多次点击,此时就会报上面的错
解决办法:show方法之前,通过isAdded 方法判断,如果已经添加就不在添加


完整代码

public void show(@NonNull FragmentManager manager) {
        if (this.isAdded()) return;
        try {
            Class<?> c = Class.forName("androidx.fragment.app.DialogFragment");
            Field dismissed = c.getDeclaredField("mDismissed");
            dismissed.setAccessible(true);
            dismissed.set(this, false);
            Field shownByMe = c.getDeclaredField("mShownByMe");
            shownByMe.setAccessible(true);
            shownByMe.set(this, true);
            FragmentTransaction fragmentTransaction = manager.beginTransaction();
            fragmentTransaction.add(this, getFragmentTag());
            fragmentTransaction.commitAllowingStateLoss();
            if (onShowDismissListener != null) onShowDismissListener.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

添加混淆

  -keep class androidx.fragment.app.DialogFragment{*;}
上一篇下一篇

猜你喜欢

热点阅读