DialogFragment.show()遇到的坑

DialogFragment.show()遇到的坑

昨天app发版上线,测试和我说注册页面点击页面按钮时崩溃了,我说不可能啊,注册页面代码我都N年没动过了,怎么会不能用了,我调试了一下,看了下日志,发现下面这个错误:

04-04 08:45:37.726 30098-30098E/AndroidRuntime: FATAL EXCEPTION: main
        Process: com.xxxx.xxxx, PID: 30098
               java.lang.IllegalStateException: Fragment RegisterDialog{196301d6 #0} declared target fragment Register2Fragment{3b3b2c57 #0 id=0x7f0e00ee} that does not belong to this FragmentManager!
               at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1352)
               at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1750)
               at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1819)
               at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:797)
               at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2590)
               at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2377)
               at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2332)
               at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2239)
               at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:700)
               at android.os.Handler.handleCallback(Handler.java:815)
               at android.os.Handler.dispatchMessage(Handler.java:104)
               at android.os.Looper.loop(Looper.java:194)
               at android.app.ActivityThread.main(ActivityThread.java:5644)
               at java.lang.reflect.Method.invoke(Native Method)
               at java.lang.reflect.Method.invoke(Method.java:372)
               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

这些日志没有指出具体错在了哪里,只能上代码了:

DialogFragment dialog = (DialogFragment) Fragment.instantiate(getContext(), RegisterDialog.class.getName(), bundle);
        dialog.setTargetFragment(this, 819);
        dialog.show(getChildFragmentManager(), null);

这个代码好久没有动过了,最近也没有改过,我想了一下除了前几天把buildToolsVersion 升到27 其他的没改啊;
还好有下面这条信息,看moveToState方法吧。
android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1352) ;

相关源码如下:

FragmentManagerImpl.class

 void moveToState(Fragment f, int newState, int transit, int transitionStyle,
            boolean keepActive) {
            ....

                        // If we have a target fragment, push it along to at least CREATED
                        // so that this one can rely on it as an initialized dependency.
                        if (f.mTarget != null) {
                            if (!mActive.contains(f.mTarget)) {
                                throw new IllegalStateException("Fragment " + f
                                        + " declared target fragment " + f.mTarget
                                        + " that does not belong to this FragmentManager!");
                            }
                            if (f.mTarget.mState < Fragment.CREATED) {
                                moveToState(f.mTarget, Fragment.CREATED, 0, 0, true);
                            }
                        }
              ...

f.mTarget != null && !mActive.contains(f.mTarget) 就会爆出这个错误。
IllegalStateException:Fragment f 和你的 mTarget 不是同一个FragmentManager。
那么我们的mTarget 和 Fragment f确实不是同一个。 mTargetFrament是依附于Activity的。
因为需要DialogFragment 有返回值所以setTargetFragment();
所以当 Activity 需要 BFrament 返回值, BFrament又需要CFrament(B的子Frament)的时候不能用此方法。

那么怎么解决呢,我是传入的getActivity().getSupportFragmentManager();

 DialogFragment dialog = (DialogFragment) Fragment.instantiate(getContext(), RegisterDialog.class.getName(), bundle);
        dialog.setTargetFragment(this, 822);
        dialog.show(getActivity().getSupportFragmentManager(), null);

这样再运行时就不会报错了,那么为什么之前没问题呢?
查看了源码。 草泥马,FragmentManagerImpl.class 26.0.0之前根本没有我上面的代码。

总结

问题找到了,根源也找到了。那么两个解决思路。
1. buildToolsVersion 降低到26.0.0。
2. FragmentManager 参数传getActivity().getSupportFragmentManager();

诶,被Google坑了一把。

你可能感兴趣的:(Android)