片段删除导致崩溃

Fragment remove causes crash

我在用户按下设置时显示设置片段button.And我想在用户从设置中单击后退按钮时将其删除。

当用户单击设置按钮时,我正在 运行 以下代码:

FragmentManager fragmentManager=getSupportFragmentManager();
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
SettingsFragment conv=new SettingsFragment();
SettingsFragment.newInstance(LOGGED_USERNAME,LOGIN_KEY);
fragmentTransaction.add(R.id.container,conv,"SettingsFragment");
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

当用户从设置片段中按下后退按钮时,我是 运行 这个:

Fragment fragment = Ffmanager.findFragmentByTag("SettingsFragment");
if(fragment != null) {
     FfTransaction.remove(fragment).commit();
}

场景:

1)主界面用户

2)点击设置按钮

3)点击设置中的后退按钮(现在一切正常)

4)再次点击设置按钮

5)然后再次点击后退按钮

那么应用是crashed.But为什么?

Logcat:

01-09 13:47:39.572: E/AndroidRuntime(2628): FATAL EXCEPTION: main
01-09 13:47:39.572: E/AndroidRuntime(2628): java.lang.IllegalStateException: commit already called
01-09 13:47:39.572: E/AndroidRuntime(2628):     at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:582)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at com.impact.app.MainActivity.fragmentCleaner(MainActivity.java:422)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at com.impact.app.MainActivity.returnFromChat(MainActivity.java:1279)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at com.impact.app.MainActivity.overrideHome(MainActivity.java:1154)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at com.impact.app.MainActivity.onOptionsItemSelected(MainActivity.java:1097)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at android.app.Activity.onMenuItemSelected(Activity.java:2566)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:373)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at com.android.internal.widget.ActionBarView.onClick(ActionBarView.java:171)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at android.view.View.performClick(View.java:4240)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at android.view.View$PerformClick.run(View.java:17721)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at android.os.Handler.handleCallback(Handler.java:730)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at android.os.Handler.dispatchMessage(Handler.java:92)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at android.os.Looper.loop(Looper.java:137)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at android.app.ActivityThread.main(ActivityThread.java:5103)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at java.lang.reflect.Method.invokeNative(Native Method)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at java.lang.reflect.Method.invoke(Method.java:525)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
01-09 13:47:39.572: E/AndroidRuntime(2628):     at dalvik.system.NativeStart.main(Native Method)

基本上你同样的FragmentTransaction两次

考虑异常信息:

  java.lang.IllegalStateException: commit already called

同时考虑:

public 抽象 int 提交 ()

Added in API level 11 Schedules a commit of this transaction. The commit does not happen immediately; it will be scheduled as work on the main thread to be done the next time that thread is ready.

A transaction can only be committed with this method prior to its containing activity saving its state. If the commit is attempted after that point, an exception will be thrown. This is because the state after the commit can be lost if the activity needs to be restored from its state. See commitAllowingStateLoss() for situations where it may be okay to lose the commit.

Returns Returns the identifier of this transaction's back stack entry, if addToBackStack(String) had been called. Otherwise, returns a negative number.

If you do not call addToBackStack() when you perform a transaction that removes a fragment, then that fragment is destroyed when the transaction is committed and the user cannot navigate back to it. Whereas, if you do call addToBackStack() when removing a fragment, then the fragment is stopped and will be resumed if the user navigates back.