我有时会收到以下崩溃报告:
java.lang.IllegalStateException:
at androidx.fragment.app.FragmentManagerImpl.addFragment (FragmentManagerImpl.java:1916)
at androidx.fragment.app.BackStackRecord.executePopOps (BackStackRecord.java:828)
at androidx.fragment.app.FragmentManagerImpl.executeOps (FragmentManagerImpl.java:2622)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether (FragmentManagerImpl.java:2411)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute (FragmentManagerImpl.java:2366)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions (FragmentManagerImpl.java:2273)
at androidx.fragment.app.FragmentManagerImpl$1.run (FragmentManagerImpl.java:733)
at android.os.Handler.handleCallback (Handler.java:808)
at android.os.Handler.dispatchMessage (Handler.java:101)
at android.os.Looper.loop (Looper.java:166)
at android.app.ActivityThread.main (ActivityThread.java:7529)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:245)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:921)
在FragmentManagerImpl的1916行中,我可以找到:
throw new IllegalStateException("Fragment already added: " + fragment);
因此它说已经添加了一些片段。不幸的是,Google不再在Google Play控制台中显示该消息(已经添加了哪个片段)。据我了解Stacktrace,当从Backstack添加片段时会发生这种异常吗?
我有一个FrameLayout
,我在其中添加/删除了片段。我总是用以下代码添加它们:
public void addFragment(FragmentActivity activity, Fragment fragment) {
FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
String tag = fragment.getClass().getCanonicalName();
Fragment prev = activity.getSupportFragmentManager().findFragmentByTag(tag);
if (fragment.isAdded()) {
return;
}
if (prev != null) {
transaction.remove(prev);
}
transaction.replace(R.id.fragment_container, fragment, tag);
transaction.addToBackStack(null);
transaction.commit();
然后使用以下方法添加DialogFragments:
public void openFragmentDialog(FragmentActivity activity, DialogFragment dialogFragment, String tag) {
FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
Fragment prev = activity.getSupportFragmentManager().findFragmentByTag(tag);
if (prev != null) {
transaction.remove(prev);
}
transaction.addToBackStack(null);
dialogFragment.show(transaction, tag);
}
在哪种情况下会发生IllegalStateException?我是否以错误的方式添加/替换了Fragments / DialogFragments?我永远无法重现该错误。但是我从Android 4.4-Android 9和所有类型的设备上收到报告,我不知道它可能在哪里发生。
是动画还是慢速设备?因为它只是偶尔发生。
答案 0 :(得分:1)
tag
必须是唯一的。如果可能的话,请用null
替换,否则请使用唯一的内容。
public void addFragment(FragmentActivity activity, Fragment fragment) {
FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
答案 1 :(得分:1)
请注意,您要添加和删除具有相同标签的两个不同片段-标签也应该不同。如果prev
片段是另一个类的实例,为什么要使用fragment
的类名作为标记来查找它?
您应该添加if
语句,以检查prev
和fragment
有时是否不是同一实例(由于相同的标记)。
如果两个片段是同一实例,并且您仍要删除然后添加相同的片段-您可能必须在两个不同的事务中执行此操作,以防止发生"Fragment already added"
异常。
答案 2 :(得分:0)
这是我要做的检查和防止重复碎片的步骤:
MyFragment myFragment = (MyFragment) fragmentManager.findFragmentByTag(MY_FRAGMENT_TAG);
if(myFragment != null && myFragment.isVisible()){
// Return early if the fragment already exists & is visible
return;
}else if(myFragment == null){
// Create a new instance of the fragment if none already exist
myFragment = new MyFragment();
}
// Perform the fragment transaction
fragmentManager.beginTransaction()
.replace(R.id.content_container, myFragment, MY_FRAGMENT_TAG)
.addToBackStack(MY_FRAGMENT_TAG) // Pass in the tag if you want to add to the back stack
.commit();
对于对话框片段,我只是创建一个新实例并在其上调用.show()
。该对话框应通过与其互动来关闭:
MyDialog myDialog = new MyDialog();
// I call getChildFragmentManager here b/c I was using this from within a fragment
// but you can get whichever Fragment Manager is appropriate
myDialog.show(getChildFragmentManager(), MY_DIALOG_TAG);