Android OnBackbackChanged()中的调用时,SDK 25.1.0在CommitNow上崩溃。谷歌Bug?
我有一个活动,有两个片段Android OnBackbackChanged()中的调用时,SDK 25.1.0在CommitNow上崩溃。谷歌Bug?,android,android-fragments,Android,Android Fragments,我有一个活动,有两个片段FragmentMainOne和FragmentMainTwo,只要调用onbackbackbackchanged(),它们就会交换 public class MainActivity extends AppCompatActivity { private int count = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCr
FragmentMainOne
和FragmentMainTwo
,只要调用onbackbackbackchanged()
,它们就会交换
public class MainActivity extends AppCompatActivity {
private int count = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
loadFragment();
getSupportFragmentManager().addOnBackStackChangedListener(
new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
loadFragment();
}
}
});
}
public void loadSubFragment() {
getSupportFragmentManager().beginTransaction().replace(R.id.view_container,
new FragmentSubOne(), FragmentSubOne.TAG).addToBackStack(FragmentSubOne.TAG).commit();
}
public void loadFragment() {
count++;
if (count % 2 == 1) {
getSupportFragmentManager().beginTransaction().replace(R.id.view_container,
new FragmentMainOne(), FragmentMainOne.TAG).commitNow();
} else {
getSupportFragmentManager().beginTransaction().replace(R.id.view_container,
new FragmentMainTwo(), FragmentMainTwo.TAG).commitNow();
}
}
}
这些代码在升级到SDK 25.1.0之前运行良好。(即25.0.0及更早版本中的OK)
升级到SDK 25.1.0后,在onbackbackbackchanged()
时,它将在commitNow()
上崩溃
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.elyeproj.commitissue, PID: 3876
java.lang.IllegalStateException: FragmentManager is already executing transactions
at android.support.v4.app.FragmentManagerImpl.ensureExecReady(FragmentManager.java:1946)
at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1965)
at android.support.v4.app.BackStackRecord.commitNow(BackStackRecord.java:614)
at com.elyeproj.commitissue.MainActivity.loadFragment(MainActivity.java:45)
at com.elyeproj.commitissue.MainActivity$1.onBackStackChanged(MainActivity.java:27)
at android.support.v4.app.FragmentManagerImpl.reportBackStackChanged(FragmentManager.java:2409)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2157)
at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2092)
at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:822)
at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:775)
at android.support.v4.app.FragmentActivity.onBackPressed(FragmentActivity.java:178)
如果我将commitNow()
切换到commit()
,它也可以正常工作。这是最新SDK上的错误,还是我遗漏了什么
注意:完整的代码可能是复制问题的访问权限
(只需加载应用程序,单击“转到子片段”,然后单击“返回”…崩溃发生。)调查后,这似乎是Support Library 25.1.0中引入的新约束 撞车发生在星期四
private void ensureExecReady(boolean allowStateLoss) {
if (mExecutingActions) {
throw new IllegalStateException("FragmentManager is already executing transactions");
}
// ... more codes
}
因此,有人将mExecutingActions
设置为true
发现在25.1.0 FragmentManager类中,下面的代码是新的
private boolean popBackStackImmediate(String name, int id, int flags) {
execPendingActions();
ensureExecReady(true);
boolean executePop = popBackStackState(mTmpRecords, mTmpIsPop, name, id, flags);
if (executePop) {
mExecutingActions = true;
try {
optimizeAndExecuteOps(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec(); // setting mExecutingAction = false
}
}
doPendingDeferredStart();
return executePop;
}
当弹出片段堆栈时,它将mExecutingActions
设置为true。这不是在25.1.0之前设置的。我认为这是一种明确的预防措施,以确保在提交另一个片段之前完成backbackback弹出
为了解决这个问题,只要我们commit()
而不是commitNow()
关于这个问题的更多说明,请参考,我认为这很好,因为当调用
onbackbackchanged()
时,fragmentManager仍在处理事务,而您正试图在manager仍在处理事务时再处理一个事务。commitNow()
与调用executePendingTransactions()完全相同
提交后。所以只有两个选择,1。使用commit()
2。使用someView.Post(new Runnable(){})
将事务放入messageQueue。谢谢@AkshayBhat'AB。我已经找到了原因,也符合你的解释。我已经贴出了答案。