我的活动布局低于
<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 of activity中,我在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。
调试我发现在fragB.isAdded()操作完成后,fragB.isAdded()返回true。在第二个菜单操作期间,fragB.isAdded()返回false并执行fragB.add()并在frameLayoutA中显示FragmentB。
我理解提交是异步操作。 isAdded返回true,因为commit是异步的,并且在调用fragB.isAdded()之前不会执行remove操作提交。这是真的吗?
请提出解决问题的可能解决方案或方法。
此致 Vibhor
答案 0 :(得分:26)
是的,事务是异步提交的。如果要在执行isAdded
之前确保所有trasactions都已完成,请运行:
getFragmentManager().executePendingTransactions();
来自executePendingTransactions()
的文档:
提交FragmentTransaction后 FragmentTransaction.commit(),它被安排执行 在进程的主线程上异步。如果你想 立即执行任何此类待处理操作,您可以调用它 函数(仅从主线程)这样做。请注意所有回调 和其他相关的行为将在这个电话中完成,所以 小心从哪里调用它。
所以你的代码应该是这样的:
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。
答案 1 :(得分:0)
也许你可以像这样包装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();
}
}
}
API级别24 中添加了commitNow()和commitNowAllowingStateLoss()
调用commitNow比调用commit()后跟executePendingTransactions()更好,因为后者的副作用是尝试提交所有当前挂起的事务,无论这是否是所需的行为。