ANDROID - java.lang.IllegalStateException:在onSaveInstanceState之后无法执行此操作

时间:2015-02-02 22:49:23

标签: java android android-fragments illegalstateexception

我在调用finish()然后重新打开应用程序时遇到上述错误。这是管理导航onBackPressed()的代码。

        android.app.FragmentManager settingsFragmentManager = getFragmentManager();
        FragmentManager fragmentManager = getSupportFragmentManager();

        if (settingsFragmentManager.getBackStackEntryCount() > 0)
            settingsFragmentManager.popBackStackImmediate();
        else if (fragmentManager.getBackStackEntryCount() > 0)
            fragmentManager.popBackStackImmediate();        

        if (fragmentManager.getBackStackEntryCount() == 0 && endIfEmpty) finish();
        if (fragmentManager.getBackStackEntryCount() == 0 && !endIfEmpty) loadView(0);
        if (fragmentManager.getBackStackEntryCount() == 0 && !userHasLoggedIn)
        {
            LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(loginBroadcastReceiver);
            finish();
        }

loadView调用方法负责根据用户选择的内容添加片段。当以0作为参数调用它时,它会添加默认片段。

这个方法:

    private void loadView(int position)
    {   
        FragmentManager fragmentManager = getSupportFragmentManager();
        Bundle fragmentArgs = new Bundle();

        if (drawerOpened)
            mDrawerLayout.closeDrawer(drawerHolderLayout);

        switch (position) {
        case 0:
            ProfileEditFragment activityList = new ProfileEditFragment();

            fragmentArgs.clear();
            fragmentArgs.putString(ProfileEditFragment.ARG_AGENT_ID, String.valueOf(prefClass.getAgentId()));
            fragmentArgs.putString(ProfileEditFragment.ARG_USERNAME, prefClass.getUsername());
            fragmentArgs.putString(ProfileEditFragment.ARG_PASSWORD, prefClass.getHashedPassword());
            fragmentArgs.putInt(ProfileEditFragment.ARG_OPERATION, ProfileEditFragment.LOAD_ALL_DATA);

            activityList.setArguments(fragmentArgs);
            fragmentManager.beginTransaction().add(R.id.main_activity_content, activityList).addToBackStack(null).commit();
            //activityList.retrieveActivityFromServer(ProfileEditFragment.LOAD_ALL_DATA);

            break;
        }
    }

执行此行时发生异常:

fragmentManager.beginTransaction().add(R.id.main_activity_content, activityList).addToBackStack(null).commit();

但是,当应用程序首次启动时,不会发生此异常。它仅在调用finish()后重新启动时出现。值得一提的是,添加的第一个片段是LoginFragment。登录过程完成后,调用popBackstack,backstack变为空,并调用loadView(0)。那么,为什么在调用loadView时会出现异常,但在添加LoginFragment时却没有?

提前致谢。

2 个答案:

答案 0 :(得分:1)

就我而言,在应用程序移至后台后,我打开了一个DialogFragment。

您可以通过以下方式模拟此状态:打开请求,运行Thread.sleep(2000),快速按智能手机上的“关闭电源”(或按“菜单”按钮),然后按“打开电源”(或打开应用程序) 。如果请求带来错误并显示DialogFragment,它将在日志中写入:java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState,对应的行是dialogFragment.show(supportFragmentManager, TAG)

我尝试了一种解决方案https://stackoverflow.com/a/22414366/2914140,它可以正常工作,但包含此错误。因此,再添加一张支票:

if (supportFragmentManager?.isStateSaved == false) {
    dialogFragment.show(supportFragmentManager, TAG)
}

在关闭屏幕,只需打开你不会看到这个对话框(伤感地说),但您的应用程序不会崩溃后,这种情况下。

更新

对不起,旧答案已经过时。参见On showing dialog i get "Can not perform this action after onSaveInstanceState"

public class CustomDialogFragment extends DialogFragment {

    @Override
    public void show(FragmentManager manager, String tag) {
        try {
            FragmentTransaction ft = manager.beginTransaction();
            ft.add(this, tag);
            ft.commit();
        } catch (IllegalStateException e) {
        }
    }
}

在这种情况下,将显示对话框片段。

答案 1 :(得分:0)

您确定在您认为的Activity实例上发生了Fragment提交吗?

我不确定我的情况是否适用于您,但我确实有类似的症状,因为我在停止并重新启动活动后才会看到异常。我还发现亚历克斯洛克伍德(非常优秀)关于这个主题的文章似乎没有帮助我,就像你在评论中提到的那样。

无论如何,我最终意识到我通过初始化一个长生命对象(在我的情况下是一个Facebook会话对象)并为它提供了一个对回调活动的引用来引发这个异常。如果Session.getActiveSession()表明会话不可用,我只会初始化会话对象。这意味着我第二次启动Activity时,将使用上一个Activity的会话,以及指向前一个Activity的回调。之前的Activity已经被销毁并且具有onSaveInstanceState。当触发回调时,旧的Activity将尝试启动其Fragment,并且发生异常。当 new Activity处于Fragment提交的有效状态时,我一直在试图弄明白我为什么会得到这个异常,但我一直试图将一个片段提交给一个旧的自从被破坏的活动。

你本身可能没有使用Facebook会话,但也许你正在做一些与长期生活对象类似的事情?

祝你好运!