getSupportFragmentManager()导致java.lang.IllegalStateException:onSaveInstanceState后无法执行此操作

Vid*_*erg 5 android android-asynctask illegalstateexception android-fragmentactivity android-support-library

我试图找出原因:

getSupportFragmentManager().beginTransaction().commit();
Run Code Online (Sandbox Code Playgroud)

失败了

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
Run Code Online (Sandbox Code Playgroud)

在一个非常基本的FragmentActivity类中.

所以这是我的用例(这将是一些伪代码,而不是一个完整的例子,抱歉):我有一个FragmentActivity与内部AsyncTask类.大概是这样的:

public class HelloWorld extends FragmentActivity {
    showFragment(Fragment fragment, String name) {
        getSupportFragmentManager().beginTransaction().replace(R.id.fragmentContainer, fragment, name).commit();
    }

    private class SlowFragmentShow extends AsyncTask<Context, String, Void> {
        protected Void doInBackground(Context... contexts) {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                /* meh */
            }
        }

        protected void onPostExecute(Void nothing) {
            showFragment(new MyFragment(), "myFragment");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

或者基本上,在启动应用程序10秒后,它将显示另一个片段.听起来很简单吧?这似乎也很有效,直到我决定旋转手机.当我这样做时,应用程序将在使用"无法执行此操作..."调用"getSupportFragmentManager()..."时崩溃.

Vid*_*erg 9

经过大量的调试后,事实证明当调用SlowFragmentShow.onPostExecute()时调用了showFragment(),而showFragment()又调用了getSupportFragmentManager(),我收到了一个处于IllegalState的FragmentManager(可以说我得到的例外是正确的) ).我仍然不确定为什么getSupportFragmentManager()会在这种状态下返回一个对象,但确实如此,我需要以某种方式访问​​"正确的"FragmentManager.因此,为了切入追逐,我将FragmentManager存储为我的HelloWorld FragmentActivity中的静态变量,我在调用HelloWorld.onStart()时更新了:

public class HelloWorld extends FragmentActivity {
    private static FragmentManager fragmentManager;

    public void onStart() {
        fragmentManager = getSupportFragmentManager();
        /* more code here */
    }

    showFragment(Fragment fragment, String name) {
        fragmentManager.beginTransaction().replace(R.id.fragmentContainer, fragment, name).commit();
    }

    private class SlowFragmentShow extends AsyncTask<Context, String, Void> {
        protected Void doInBackground(Context... contexts) {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                /* meh */
            }
        }

        protected void onPostExecute(Void nothing) {
            showFragment(new MyFragment(), "myFragment");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

好吧,这几乎解决了它.现在我可以将手机旋转到我心中的愿望,当AsyncTask完成时,片段仍会显示.

回想起来,它看起来确实有点"哦,当然!",但Android背后的设计决策感觉非常"异常"和不同寻常.我似乎最终只有一半代码的try-catch(Exception)只是为了防止它在非致命错误(例如无法更新文本字段)和许多需要的静态变量上崩溃在onStart()上更新,因为这似乎是唯一能够引用Android对象而没有它们处于"IllegalState"的理智方式.

  • 在创建片段期间调用`setRetainInstance(true)`.然后在`onPostExecute()`中调用`getSupportFragmentManager()`来获取`SupportFragmentManager`.但是,在英语中,"很多"意味着不止一个案例,这就是为什么我建议您提出一个新的StackOverflow问题,并举例说明这一点,以便人们可以帮助您制定更好的策略. (3认同)