为什么Android操作系统失败了“不属于这个碎片管理器!”

时间:2021-04-18 18:59:15

I have migrated my application to Android O in Android Studio 3

我已经将我的应用程序迁移到安卓(Android) Studio 3。

Running on an Android O emulator all my dialogFragments now fail with :-

在Android O模拟器上运行我所有的对话框现在都失败了:-。

java.lang.IllegalStateException: Fragment MyDialogFragment{43ccf50 #2 MyDialogFragment} declared target fragment SettingsFragment{ceed549 #0 id=0x7f0f0142 android:switcher:2131689794:0} that does not belong to this FragmentManager!
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1316)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1624)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1689)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:794)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2470)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2260)
at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2213)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2122)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:746)
at android.os.Handler.handleCallback(Handler.java:769)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6535)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

I have made no code changes whatsoever.

我没有任何代码变更。

What has changed in Android O that previously working DialogFragments now fail display?

在Android操作系统中,以前工作的对话框现在不能显示什么?

Android Studio 3.0 Canary 1
Build #AI-171.4010489, built on May 15, 2017
JRE: 1.8.0_112-release-b736 x86_64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Mac OS X 10.11.6

    compileSdkVersion 'android-O'
    buildToolsVersion "26.0.0-rc2"

   AndroidManifest.xml
    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 'O'
        }

compile 'com.android.support:appcompat-v7:26.0.0-beta1'
compile 'com.android.support:cardview-v7:26.0.0-beta1'
compile 'com.android.support:design:26.0.0-beta1'
    compile 'com.android.support:percent:26.0.0-beta1'

  dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0-alpha1'

    }

4 个解决方案

#1


11  

I had the same problem, definitely an android bug. It happens when you are showing a fragment from another fragment using it as target. As workaround you can use:

我遇到了同样的问题,肯定是android bug。当您从另一个片段中使用它作为目标显示一个片段时,就会发生这种情况。作为变通方法,你可以使用:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
    getActivity().getFragmentManager().beginTransaction().add(dialogFrag, "dialog").commit();
else
    getChildFragmentManager().beginTransaction().add(dialogFrag,"dialog").commit();

#2


32  

For me this was not only an issue on Android O but also on older versions. The oldest version I tested was API Level 16.

对我来说,这不仅是Android操作系统的问题,也是老版本的问题。我测试的最老版本是API级别16。

I was instantiating my fragments using this code:

我用这个代码实例化了我的片段:

MyFragment myFragment = MyFragment.newInstance();
myFragment.setTargetFragment(ParentFragment.this, 0);
myFragment.show(getActivity().getSupportFragmentManager(), null);

Where ParentFragment.this is a custom class extending android.support.v4.app.Fragment, MyFragment also extends this class and is a child fragment of the ParentFragment fragment (hence it's name).

ParentFragment的地方。这是一个扩展android.support.v4.app的自定义类。片段,MyFragment也扩展了这个类,它是ParentFragment片段的子片段(因此它是name)。

I thought that I had to use a SupportFragmentManager (the getSupportFragmentManager() method) because I am using a fragment of the support package so I tried to call getActivity().getSupportFragmentManager() to get an activity reference that supported this method.

我认为我必须使用一个SupportFragmentManager(getSupportFragmentManager()方法),因为我使用的是一个支持包的片段,所以我尝试调用getActivity().getSupportFragmentManager()来获得支持该方法的活动引用。

This does not seem to be the correct way though. I changed those calls to:

但这似乎并不是正确的方法。我把电话转到:

MyFragment myFragment = MyFragment.newInstance();
myFragment.setTargetFragment(ParentFragment.this, 0);
myFragment.show(getFragmentManager(), null);

so the fragment decides on it's own which FragmentManager to use and the error is gone now.

因此,碎片决定使用哪个片段管理器,错误现在就消失了。

Hope this helps someone.

希望这可以帮助别人。

#3


4  

I just faced the same issues in the project that I am currently working on when we moved to Android Studio 3 and upgraded the support library to version 26. All of a sudden, without changing the code, we got tons of this exception. In the end I found out the following:

我刚刚在我正在做的项目中遇到了同样的问题,当我们移动到Android Studio 3并将支持库升级到第26版时。突然间,在不改变代码的情况下,我们得到了大量的异常。最后我发现了以下几点:

Google added a new "sanity check" in the sources of the v4 Fragment Manager in January this year (not sure into what release that went) that refuses to add a fragment using a Fragment Manager, if it has a target fragment set and the target fragment cannot be found in the active fragments of the same Fragment Manager. The patch is described in detail here

谷歌添加了一个新的“检查”的来源v4片段经理今年1月(不确定到什么版本了),拒绝使用片段管理器添加一个片段,如果它有一个目标片段集和目标片段无法找到相同的片段活性片段的经理。这里详细描述了补丁。

Ealier versions seem to not have cared about that. Took me a few days to update all the areas in our code where fragments that were added using the Support Fragment Manager used the Child Fragment Manager for their subfragments with the parent fragment as target. Well, late penalty for writing bad code.

Ealier版本似乎对此并不在意。我花了几天时间更新代码中的所有区域,其中使用支持片段管理器添加的片段使用子片段管理器将父片段作为目标。好吧,写坏代码的时候要迟到了。

#4


4  

I had the same case as Markus Ressel but I was using getChildFragmentManager(). I replaced that with getFragmentManager() and it resolved the issue.

我和Markus Ressel有同样的情况,但我使用的是getChildFragmentManager()。我用getFragmentManager()替换了它,并解决了这个问题。

UPDATE: I've now been working with childFragmentManager and have some feedback.

更新:我现在和孩子们一起工作,并得到了一些反馈。

When dealing with inner fragments that are hosted by a fragment (so a fragment within a fragment) use the childFragmentManager. This fragment manager differs from the activities getSupportFragmentManager. The two are not the same. It's a separation of concerns.

当处理由片段(片段内的片段)托管的内部片段时,请使用childFragmentManager。这个片段管理器与活动getSupportFragmentManager不同。这两个不一样。这是关注点的分离。

So I've made a rule that fragments hosting child fragments will always use the childFragmentManager and things not inside host fragments can use getSupportfragmentManager.

因此,我已经制定了一个规则,片段托管子片段将始终使用childFragmentManager,而非宿主片段内的东西可以使用getSupportfragmentManager。

#1


11  

I had the same problem, definitely an android bug. It happens when you are showing a fragment from another fragment using it as target. As workaround you can use:

我遇到了同样的问题,肯定是android bug。当您从另一个片段中使用它作为目标显示一个片段时,就会发生这种情况。作为变通方法,你可以使用:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
    getActivity().getFragmentManager().beginTransaction().add(dialogFrag, "dialog").commit();
else
    getChildFragmentManager().beginTransaction().add(dialogFrag,"dialog").commit();

#2


32  

For me this was not only an issue on Android O but also on older versions. The oldest version I tested was API Level 16.

对我来说,这不仅是Android操作系统的问题,也是老版本的问题。我测试的最老版本是API级别16。

I was instantiating my fragments using this code:

我用这个代码实例化了我的片段:

MyFragment myFragment = MyFragment.newInstance();
myFragment.setTargetFragment(ParentFragment.this, 0);
myFragment.show(getActivity().getSupportFragmentManager(), null);

Where ParentFragment.this is a custom class extending android.support.v4.app.Fragment, MyFragment also extends this class and is a child fragment of the ParentFragment fragment (hence it's name).

ParentFragment的地方。这是一个扩展android.support.v4.app的自定义类。片段,MyFragment也扩展了这个类,它是ParentFragment片段的子片段(因此它是name)。

I thought that I had to use a SupportFragmentManager (the getSupportFragmentManager() method) because I am using a fragment of the support package so I tried to call getActivity().getSupportFragmentManager() to get an activity reference that supported this method.

我认为我必须使用一个SupportFragmentManager(getSupportFragmentManager()方法),因为我使用的是一个支持包的片段,所以我尝试调用getActivity().getSupportFragmentManager()来获得支持该方法的活动引用。

This does not seem to be the correct way though. I changed those calls to:

但这似乎并不是正确的方法。我把电话转到:

MyFragment myFragment = MyFragment.newInstance();
myFragment.setTargetFragment(ParentFragment.this, 0);
myFragment.show(getFragmentManager(), null);

so the fragment decides on it's own which FragmentManager to use and the error is gone now.

因此,碎片决定使用哪个片段管理器,错误现在就消失了。

Hope this helps someone.

希望这可以帮助别人。

#3


4  

I just faced the same issues in the project that I am currently working on when we moved to Android Studio 3 and upgraded the support library to version 26. All of a sudden, without changing the code, we got tons of this exception. In the end I found out the following:

我刚刚在我正在做的项目中遇到了同样的问题,当我们移动到Android Studio 3并将支持库升级到第26版时。突然间,在不改变代码的情况下,我们得到了大量的异常。最后我发现了以下几点:

Google added a new "sanity check" in the sources of the v4 Fragment Manager in January this year (not sure into what release that went) that refuses to add a fragment using a Fragment Manager, if it has a target fragment set and the target fragment cannot be found in the active fragments of the same Fragment Manager. The patch is described in detail here

谷歌添加了一个新的“检查”的来源v4片段经理今年1月(不确定到什么版本了),拒绝使用片段管理器添加一个片段,如果它有一个目标片段集和目标片段无法找到相同的片段活性片段的经理。这里详细描述了补丁。

Ealier versions seem to not have cared about that. Took me a few days to update all the areas in our code where fragments that were added using the Support Fragment Manager used the Child Fragment Manager for their subfragments with the parent fragment as target. Well, late penalty for writing bad code.

Ealier版本似乎对此并不在意。我花了几天时间更新代码中的所有区域,其中使用支持片段管理器添加的片段使用子片段管理器将父片段作为目标。好吧,写坏代码的时候要迟到了。

#4


4  

I had the same case as Markus Ressel but I was using getChildFragmentManager(). I replaced that with getFragmentManager() and it resolved the issue.

我和Markus Ressel有同样的情况,但我使用的是getChildFragmentManager()。我用getFragmentManager()替换了它,并解决了这个问题。

UPDATE: I've now been working with childFragmentManager and have some feedback.

更新:我现在和孩子们一起工作,并得到了一些反馈。

When dealing with inner fragments that are hosted by a fragment (so a fragment within a fragment) use the childFragmentManager. This fragment manager differs from the activities getSupportFragmentManager. The two are not the same. It's a separation of concerns.

当处理由片段(片段内的片段)托管的内部片段时,请使用childFragmentManager。这个片段管理器与活动getSupportFragmentManager不同。这两个不一样。这是关注点的分离。

So I've made a rule that fragments hosting child fragments will always use the childFragmentManager and things not inside host fragments can use getSupportfragmentManager.

因此,我已经制定了一个规则,片段托管子片段将始终使用childFragmentManager,而非宿主片段内的东西可以使用getSupportfragmentManager。