I have a very simple FragmentActivity which using android.support.v4 library, there are only a TabHost inside the FragmentActivity, which contain 4 fragment.

No async task, no implementation of onSaveInstanceState().

After few week on the market I got lot of exception report called "java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState" (see stack trace on below), all from Samsung device(SM-N9003, GT-I9305, GT-N7100...etc.), totally no ideas what's going wrong.

I have searched some similar question before, but no answer at all.

Layout :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <FrameLayout
        android:id="@+id/realtabcontent"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <android.support.v4.app.FragmentTabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="0" />
    </android.support.v4.app.FragmentTabHost>

</LinearLayout>

Code :

private void setupTabs() {
    FragmentTabHost tabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
    tabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);

    tabHost.addTab(setIndicator(this, tabHost.newTabSpec(FragmentList), getString(R.string.tabwidget_List), R.drawable.btn_icon_order), ListFragment.class, null);
    tabHost.addTab(setIndicator(this, tabHost.newTabSpec(FragmentSwitch), getString(R.string.tabwidget_Switch), R.drawable.btn_icon_switch), SwitchFragment.class, null);
    tabHost.addTab(setIndicator(this, tabHost.newTabSpec(FragmentQueue), getString(R.string.tabwidget_Queue), R.drawable.btn_icon_queue), QueueFragment.class, null);
    tabHost.addTab(setIndicator(this, tabHost.newTabSpec(FragmentMore), getString(R.string.tabwidget_More), R.drawable.btn_icon_more), MoreFragment.class, null);

}

private TabSpec setIndicator(Context context, TabSpec tabSpec, String Title,int resId) {
    View view = LayoutInflater.from(context).inflate(R.layout.tab_widget, null);

    ImageView ivTTIcon = (ImageView) view.findViewById(R.id.ivTTIcon);
    ivTTIcon.setImageResource(resId);

    TextView tvTTText = (TextView) view.findViewById(R.id.tvTTText);
    tvTTText.setText(Title);

    return tabSpec.setIndicator(view);
}

Stack trace :

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1343)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1354)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
at android.support.v4.app.FragmentTabHost.onTabChanged(FragmentTabHost.java:309)
at android.widget.TabHost.invokeOnTabChangeListener(TabHost.java:463)
at android.widget.TabHost.setCurrentTab(TabHost.java:448) at android.widget.TabHost$2.onTabSelectionChanged(TabHost.java:161)
at android.widget.TabWidget$TabClickListener.onClick(TabWidget.java:563)
at android.view.View.performClick(View.java:4475) at android.view.View$PerformClick.run(View.java:18784) at android.os.Handler.handleCallback(Handler.java:730) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5414) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
at dalvik.system.NativeStart.main(Native Method)

2

There are 2 answers

2
natez0r On

What this error means is that you are committing a FragmentTransaction after the activity state has been saved and the transaction won't be restored when the activity is restored. There is some documentation here: http://developer.android.com/reference/android/app/FragmentTransaction.html#commit() about what you can do to work around this, but you will need to make sure that you are only committing fragment transactions when the activity/fragment is in the state to accept them (for fragments: isResumed() returning true is a good start). You could use the nuclear options of commitAllowingStateLoss() if need be, but I would recommend trying to dig into the places where you call commit() and when those could be called in relation to the Activity/Fragment lifecycle.

Sorry I don't have samsung specific solutions, but hopefully this will provide a starting point.

1
ALearner On

Here is the solution,

This problem occurs if tab selection action performs after onSaveInstanceState get called. One example like, if user selects and holds any tab and at the same time also selects the Home Button.

To solve this issue just call mTabHost.getTabWidget().setEnabled(false); under onPause of the Fragment/Activity and call mTabHost.getTabWidget().setEnabled(true); under onResume.