如何判断onSaveInstanceState()被调用以避免IllegalStateException?

7
当用户在导航抽屉中选择一个项目时,我的应用程序会启动一个处理程序,等待抽屉关闭后调用代码来替换主Activity中的片段。然而,如果设备在延迟期间旋转,我会收到一个IllegalStateException异常。
我阅读了这篇关于片段事务和生命周期的精彩文章,但我不确定如何在我的代码中处理这个问题。我明白我不应该在onSaveInstanceState()之后尝试提交事务。但是,我怎么知道onSaveInstanceState()是否已被调用?我想做这样的事情。
navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(final MenuItem menuItem) {
        // close drawers
        drawerLayout.closeDrawers();

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                goTo(menuItem); // swap in Fragment specified by menuItem
            }
        }, 300);
        return true;
    }
    });
...
private void goTo(menuItem) {
    if( alreadyCalledOnSaveInstanceState() {  // THIS
        return;
    }

    switch (item.getItemId()) {
        case R.id.item1:
            frag = new Fragment_Grade_Calculator();
            getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.slide_in_up, R.anim.zoom_exit).replace(R.id.main_frag_container, frag)
                    .commit();
            return true;
}

但我不知道有没有类似于我编造的alreadyCalledOnSaveInstanceState()的等效方法。


1
最终我只是在调用goTo(menuItem)的地方加了一个try/catch。 这对我的目的很有效 - 片段永远不会被交换,这比崩溃要好。 - NSouth
2个回答

0
我认为你不应该使用 onSaveInstanceState(),而是使用 onStop()。在 onStop() 被调用后不要提交事务。并且不要忘记在 onStart() 被调用后允许提交你的事务。

1
你是说我应该手动跟踪 onSaveInstanceState()onStop() 是否已经被调用了吗? - NSouth
1
本文专门针对您的问题:http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html - ivan

0
据我所知,onSaveInstanceState()方法在onPause()方法之前永远不会被调用。因此,只要您在恢复状态下提交片段事务,就不会遇到IllegalStateException异常。

根据文档,在 Android P 之后,onSaveInstanceState 在 onStop 之后被保证会被调用。但是在 Android P 之前,onSaveInstanceState 将在 onStop 之前被调用,并且无法保证它会在 onPause 之前或之后发生。 https://developer.android.com/reference/android/app/Activity#onSaveInstanceState(android.os.Bundle) - eliasbagley

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