java.lang.IllegalStateException:在创建活动期间的FragmentTabHost中onSaveInstanceState之后无法执行此操作

9
我正在尝试在FragmentActivity中使用v4支持库中的FragmentTabHost中的Fragment。这个异常在Activity OnCreate期间被抛出,就像Alex指出的可能情况一样,但仍然在activity oncreate中提交片段事务。由于这个异常,我的活动显示为空的tabcontent和标签。
注意: 1)我锁定了屏幕旋转 - 没有方向条件。 2)这发生在初始阶段的activity oncreate中。 3)我在Activity OnCreate()中使用commit()。 4)如日志所指,commit关系是从TabHost而不是从我的一侧完成的。
以下是我的日志:
03-29 11:32:55.975: E/AndroidRuntime(27470): java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1343)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1361)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.support.v4.app.FragmentTabHost.onAttachedToWindow(FragmentTabHost.java:282)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.view.View.dispatchAttachedToWindow(View.java:9924)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2198)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2206)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2206)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2206)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2206)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2206)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2206)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1079)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2585)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.os.Handler.dispatchMessage(Handler.java:99)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.os.Looper.loop(Looper.java:137)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at android.app.ActivityThread.main(ActivityThread.java:4507)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at java.lang.reflect.Method.invokeNative(Native Method)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at java.lang.reflect.Method.invoke(Method.java:511)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
03-29 11:32:55.975: E/AndroidRuntime(27470):    at dalvik.system.NativeStart.main(Native Method)

这是我的代码

活动:

private void addFragmentToStack(int originCurrentSplitNo, boolean isOrgin,
            int holderId) {

        // Instantiate a new fragment(FragmentTabhost as the layout of this).
        SplitFragment newFragment = SplitFragment.newInstance();


        // Add the fragment to the activity, pushing this transaction
        // on to the back stack.
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(holderId, (Fragment) newFragment,
                newFragment.getCurrentFragmentTag());
        if (null == fragmentTagHolder) {
            fragmentTagHolder = new ArrayList<String>();
        }
    //tag holders in the activity
        fragmentTagHolder.add(newFragment.getCurrentFragmentTag());
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.addToBackStack(null);
        ft.commit();
    }

这是一个包含FragmentTabHost并将附加到Activity的片段。

//SplitFragment.java

private View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if (container == null) {
            // Currently in a layout without a container, so no
            // reason to create our view.
            return null;
        }


        View fragmentTabHostView = inflater.inflate(R.layout.fragment_tab_host_layout, container,
                false);
        initFrgmentTab(fragmentTabHostView );
        return fragmentTabHostView;
    }

    private View initFrgmentTab(View oemView) {
        if (null == fragmentTabHostView ) {
            return null;
        }

        typeViewHost = (FragmentTabHost) fragmentTabHostView 
                .findViewById(android.R.id.tabhost);

        if (!(null == typeViewHost)) {

            typeViewHost.setup(getActivity().getApplicationContext(), getChildFragmentManager(),android.R.id.tabcontent);

            LinkedHashMap<Integer, fragmentTabContent> frgmentTabContent = ((OEMCarInspectionActivity) getActivity())
                    .getfrgmentTabContent Details();
    Set<Integer> views = frgmentTabContent .getKeySet();
    //Creating the tabs
            for (Integer viewCode : views) {
                fragmentTabContent carView = carTypeViews.get(viewCode );
                String tabTitle = fragmentTabContent.getViewDescription();

                if (null == tabTitle || tabTitle .trim().isEmpty()) {
                    continue;
                }
                Bundle tabViewBundle = new Bundle();
                carViewBundle.putInt(CarViewFragment.CARVIEW_CODE_KEY,
                        viewCode);
                typeViewHost.addTab(typeViewHost.newTabSpec(tabTitle )
                        .setIndicator(tabTitle ), TabViewFragment.class,
                        tabViewBundle);

            }
}

作为FragmentTabHost的选项卡内容,需要使用片段(Fragment)来扮演该角色。
//TabViewFragment.java
/**
     * The Fragment's UI is just a simple text view showing its instance number.
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if (null == container) {
            // Currently in a layout without a container, so no
            // reason to create our view.
            return null;
        }

        View v = inflater.inflate(R.layout.tab_view_layout, container,
                false);

        return v;
    }

FragmentTabHost的布局:

//fragment_tab_host_layout.xml(layout for SplitFragment.java )

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.app.FragmentTabHost 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="0"
            android:orientation="vertical" >


            <HorizontalScrollView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:fillViewport="true"
                android:scrollbars="none" >

                <TabWidget
                    android:id="@android:id/tabs"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal" />
            </HorizontalScrollView>
        </LinearLayout>

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:layout_weight="1" >

            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="0dp"
                android:layout_height="0dp" />
        </RelativeLayout>
    </LinearLayout>

</android.support.v4.app.FragmentTabHost>
2个回答

0

我有一个解决方案:

  1. 复制FragmentTabHost的所有代码。
  2. 将它粘贴到项目中的新类中,并将其命名为MyTabHost。
  3. 将代码中所有的commit()替换为commitAllowStateLoss()。
  4. 在你的项目中使用这个类 - MyTabHost,而不是FragmentTabHost。

它丑陋得要死,但它可行。


0

最初,我认为这很可能是一个旋转问题。但是通过您提供的额外细节,我认为我看到了问题所在。

您正在 onCreateView 中初始化 tabhost。 在 onCreateView 中,该片段尚未添加到活动中; 它只是被要求提供其布局。 可能会话状态尚未恢复(就片段事务管理器而言),因为它实际上处于构建状态(正在插入视图)。

尝试将 tabhost 初始化代码移到 onActivityCreated 中,在插入视图后调用。即:

private View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if (container == null) {
            // Currently in a layout without a container, so no
            // reason to create our view.
            return null;
        }


        View fragmentTabHostView = inflater.inflate(R.layout.fragment_tab_host_layout, container,
                false);

        return fragmentTabHostView;
    }

public void onActivityCreated (Bundle savedInstanceState) {
       initFrgmentTab(getView());
}

如果仍然出现问题,尝试将其移动到onResume(在状态已经恢复之后)来解决。

谢谢回复,我想之前可能没有提供所有信息,但现在我已经更新了,并附上了注释。 - user3475098
“快速”修复方法是使用“ft.commitAllowingStateLoss();”而不是“ft.commit();”,但我怀疑该方法存在潜在问题。 - C B J
它只会避免抛出异常,但不会解决问题。但无论如何,异常是由TabHost抛出的,内部tabhost执行了ft.commit()。 - user3475098

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接