【问题标题】:Why I am getting "Cannot remove Fragment attached to a different FragmentManager" in Android?为什么我在 Android 中收到“无法删除附加到不同 FragmentManager 的 Fragment”?
【发布时间】:2019-04-05 10:09:19
【问题描述】:

我正在尝试删除一个片段,但在 Crashlytics 上我很少看到错误 java.lang.IllegalStateException: Cannot remove Fragment attach to a different FragmentManager。

我有一个单独的片段用于获取用户的当前位置。我使用下面的代码打开片段。

private void openLocationFragment() {
    LocationFragment locationFragment = LocationFragment.newInstance();
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.beginTransaction()
            .replace(R.id.fragmentContainer, locationFragment, "location_fragment")
            .commitAllowingStateLoss();
}

现在在片段中,一旦我获得位置更新,我就会使用附加到活动的侦听器调用 onLocationFetched 方法。

在此方法中,我使用以下代码删除片段。

@Override
public void onLocationFetched(Location location) {
    FragmentManager fragmentManager = getSupportFragmentManager();
    LocationFragment locationFragment = (LocationFragment) fragmentManager.findFragmentByTag("location_fragment");
    if (locationFragment != null) {
        fragmentManager.beginTransaction()
                .remove(locationFragment) // Here is the exception
                .commitAllowingStateLoss();
    }
    if(location == null){
        fetchUserDetails();
    }else
        fetchCity(location);
}

堆栈跟踪:

Fatal Exception: **java.lang.IllegalStateException: Cannot remove Fragment attached to a different FragmentManager.** 

Fragment LocationFragment{32a2ed0 (d41fc341-baf2-4266-948a-866fba7e57b5) id=0x7f09028b location_fragment} is already attached to a FragmentManager.
       at androidx.fragment.app.BackStackRecord.remove(BackStackRecord.java:316)
       at com.avail.easyloans.feature.marketplace.activities.ActivityMarketplace.onFragmentFetched(ActivityMarketplace.java:909)
       at com.avail.easyloans.base.fragments.LocationFragment.sendLocationToClient(LocationFragment.java:192)
       at com.avail.easyloans.base.fragments.LocationFragment.access$000(LocationFragment.java:46)
       at com.avail.easyloans.base.fragments.LocationFragment$4.onSuccess(LocationFragment.java:220)
       at com.avail.easyloans.base.fragments.LocationFragment$4.onSuccess(LocationFragment.java:214)
       at com.google.android.gms.tasks.zzn.run(zzn.java:4)
       at android.os.Handler.handleCallback(Handler.java:836)
       at android.os.Handler.dispatchMessage(Handler.java:103)
       at android.os.Looper.loop(Looper.java:203)
       at android.app.ActivityThread.main(ActivityThread.java:6339)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1084)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:945)

我在这里做错了什么?

【问题讨论】:

  • 你是从不同的活动中打电话给getSupportFragmentManager()吗?
  • 是的,但此片段未用于任何其他活动。
  • 这可以解释你的错误 - 每个活动都有自己的FragmentManager 来管理自己的片段
  • @PPartisan 如果这个片段没有用于任何其他活动,它仍然会影响FragmentManager
  • 您可以检查容器的资源 id 值,而不是使用 findFragmentById() 的标记值。或者,您可以启动包含您的位置片段的其他活动

标签: android android-fragments fragmentmanager


【解决方案1】:

我希望每个Activity 负责维护自己的Fragments。这意味着如果您尝试访问的 Fragment 与另一个 ActivityFragmentManager 相关联,那么您的应用将失败。

我可以想出几种解决方法,具体取决于您想要的行为。如果您不介意两个 LocationFragments 在两个单独的活动中拥有自己单独的生命周期,您可以在 FragmentManager 上使用 findFragmentById() 访问它们。即:

private void openLocationFragment() {
    FragmentManager fragmentManager = getSupportFragmentManager();
    final Fragment current = fragmentManager.findFragmentById(R.id.fragmentContainer);
    if(current == null || !(current instanceof LocationFragment)) {
        fragmentManager.beginTransaction()
            .replace(R.id.fragmentContainer, LocationFragment.newInstance())
            .commitAllowingStateLoss();
    }
}

并在您的其他活动中执行相同的操作。或者,您可以调用在onLocationFetched() 中托管LocationFragment 的其他Activity

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-01
    相关资源
    最近更新 更多