从容器中删除片段后,Fragment.isAdded返回true

我有一个以下布局的活动

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > <FrameLayout android:id="@+id/frameLayoutA" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_weight="1" > </FrameLayout> <FrameLayout android:id="@+id/frameLayoutB" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_weight="1" > </FrameLayout> </LinearLayout> 

在活动的onCreate中,我加载了frameLayoutA中的Fragment_A和frameLayoutB中的Fragment_B。

 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); fmA=(FrameLayout) findViewById(R.id.frameLayoutA); fmB=(FrameLayout) findViewById(R.id.frameLayoutB); fragA=new FragmentA(); fragB=new FragmentB(); fragC=new FragmentC(); addFragmentsInActivity(R.id.frameLayoutA,fragA); addFragmentsInActivity(R.id.frameLayoutB,fragB); } public void addFragmentsInActivity(int id, Fragment fragment) { FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.add(id, fragment); fragmentTransaction.commit(); } 

使用菜单操作,我想加载frameLayoutA中的Fragment_B和frameLayoutB中的Fragment_C。 菜单操作是:

  removeFragmentsInActivity(R.id.frameLayoutB,fragB); addFragmentsInActivity(R.id.frameLayoutB,fragC); if(!fragB.isAdded()){ Log.e("check", "fragB already removed from frameLayoutB"); removeFragmentsInActivity(R.id.frameLayoutB,fragB); addFragmentsInActivity(R.id.frameLayoutA,fragB); } else{ Log.e("check", "fragB already added"); } public void removeFragmentsInActivity(int id, Fragment fragment) { FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.remove(fragment); fragmentTransaction.commit(); } 

Fragment_B不显示在frameLayoutA中。 frameLayoutA显示Fragment_A。 当再次点击菜单操作时,Fragment_B被加载。

debugging我发现在fragB.isAdded()在fragB.remove()操作完成后返回true。 在第二个菜单操作期间,fragB.isAdded()返回false,执行fragB.add(),FragmentB显示在frameLayoutA中。

我明白提交是一个asynchronous操作。 isAdded返回true,因为commit是asynchronous的,直到调用fragB.isAdded()的时候才删除操作提交。 这是真的吗?

请提出可能的解决scheme或方法来解决问题。

问候,Vibhor

Solutions Collecting From Web of "从容器中删除片段后,Fragment.isAdded返回true"

是的事务是asynchronous提交的。 如果要在执行isAdded之前确保所有交易已完成,请运行:

 getFragmentManager().executePendingTransactions(); 

来自executePendingTransactions()文档:

在使用FragmentTransaction.commit()提交FragmentTransaction后,计划在进程的主线程上asynchronous执行。 如果你想立即执行任何这样的挂起操作,你可以调用这个函数(只能从主线程)来这样做。 请注意,所有callback和其他相关行为都将在此调用中完成,因此请注意从何处调用。

所以你的代码应该是这样的:

 removeFragmentsInActivity(R.id.frameLayoutB,fragB); addFragmentsInActivity(R.id.frameLayoutB,fragC); getFragmentManager().executePendingTransactions(); if(!fragB.isAdded()){ Log.e("check", "fragB already removed from frameLayoutB"); removeFragmentsInActivity(R.id.frameLayoutA,fragA); addFragmentsInActivity(R.id.frameLayoutA,fragB); } else{ Log.e("check", "fragB already added"); } 

注意也固定删除片段A.

也许你可以这样捕捉FragmentTransaction的共同点

 private void commitFragmentTransaction(final FragmentTransaction ft, boolean allowStateLoss, boolean now) { if (ft == null || ft.isEmpty()) { return; } if (allowStateLoss) { if (now) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { ft.commitNowAllowingStateLoss(); } else { ft.commitAllowingStateLoss(); mFragmentManager.executePendingTransactions(); } } else { ft.commitAllowingStateLoss(); } } else { if (now) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { ft.commitNow(); } else { ft.commit(); mFragmentManager.executePendingTransactions(); } } else { ft.commit(); } } } 

commitNow()和commitNowAllowingStateLoss()在API级别24中添加

调用commitNow比调用commit()后跟executePendingTransactions()更可取,因为后者将具有尝试提交所有当前未决事务的副作用,无论这是否是所需的行为。