为什么在Android中我收到“无法删除附加到不同FragmentManager的Fragment”的错误消息?

6

我正在尝试删除一个片段,但是很少在Crashlytics上能够看到一个bug:java.lang.IllegalStateException: Cannot remove Fragment attached 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)

我在这里做错了什么?

你是否从不同的Activities中调用了getSupportFragmentManager()方法? - PPartisan
是的,但这个片段没有在任何其他活动中使用。 - Prashant Jha
@PPartisan 如果此片段未在任何其他活动中使用,它是否仍会影响 FragmentManager - Prashant Jha
你可以使用findFragmentById()来检查容器的资源id值,而不是通过标记值进行检查。或者,您可以启动包含位置片段的其他Activity。 - PPartisan
@PPartisan,你能提供一些代码作为参考吗?我无法理解你想表达什么。 - Prashant Jha
显示剩余2条评论
1个回答

5
我期望每个Activity都负责维护自己的Fragment。这意味着,如果你正在尝试访问与另一个ActivityFragmentManager相关联的Fragment,则你的应用将失败。
我可以想到几种解决方法,具体取决于您想要的行为。如果您不介意在两个独立的活动中拥有两个LocationFragment,并且它们各自具有各自的生命周期,则可以使用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();
    }
}

在您的另一个Activity中同样执行此操作。或者,您可以在onLocationFetched()方法中调用托管LocationFragment的其他Activity


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接