切换选项卡 onNewIntent 导致 IllegalStateException

Posted

技术标签:

【中文标题】切换选项卡 onNewIntent 导致 IllegalStateException【英文标题】:Switch tab onNewIntent cause IllegalStateException 【发布时间】:2012-07-12 13:49:28 【问题描述】:

如果我尝试在 onNewIntent 方法中切换导航选项卡,我的 FragmentActivity(singleTop) 会给我 IllegalStateException。

更具体地说,我的应用程序使用带有三个选项卡的 SherlockActionBar,当收到推送通知(并调用意图)时更新一个选项卡,如果应用程序暂停在另一个选项卡上,当我收到意图时(在 onNewIntent ) 我使用 bar.setSelectedNavigationItem() 将选项卡(以及片段)更改为第三个选项卡,这导致了我的问题。如果应用程序在第三个选项卡上被暂停,则不会发生异常。

代码:

@Override
    public void onNewIntent(Intent intent) 
        super.onNewIntent(intent);
        Bundle bundle = intent.getExtras();
        if (bundle != null) 
            bar.setSelectedNavigationItem(Utils.ORDER_STATUS_TAB_ID);
         else 
        
     

推送通知意图:

    Intent notificationIntent = new Intent(context,
            MainActivity.class);
    notificationIntent.putExtra("orderUpdate",
            new Gson().toJson(orderUpdate));
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
            | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
            notificationIntent, 0);

    notification.contentIntent = contentIntent;

TabListener 方法(在堆栈跟踪中的第 56 行带有注释)

@Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) 
        ft = activity.getSupportFragmentManager().beginTransaction();
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        if (mFragment == null) 
            mFragment = Fragment
                    .instantiate(activity, mClass.getName(), mArgs);
            ft.add(android.R.id.content, mFragment, tag);
            ft.commit();
         else 
            ft.attach(mFragment);
            ft.commit(); // line 56
        

详细异常:

07-12 20:06:40.959: E/AndroidRuntime(8639): java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
07-12 20:06:40.959: E/AndroidRuntime(8639):     at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1299)
07-12 20:06:40.959: E/AndroidRuntime(8639):     at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1310)
07-12 20:06:40.959: E/AndroidRuntime(8639):     at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:541)
07-12 20:06:40.959: E/AndroidRuntime(8639):     at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:525)
07-12 20:06:40.959: E/AndroidRuntime(8639):     at com.wizche.ui.MyTabListener.onTabSelected(MyTabListener.java:56)
07-12 20:06:40.959: E/AndroidRuntime(8639):     at com.actionbarsherlock.internal.app.ActionBarImpl.selectTab(ActionBarImpl.java:526)
07-12 20:06:40.959: E/AndroidRuntime(8639):     at com.actionbarsherlock.internal.app.ActionBarImpl.setSelectedNavigationItem(ActionBarImpl.java:317)
07-12 20:06:40.959: E/AndroidRuntime(8639):     at com.wizche.MainActivity.onNewIntent(MainActivity.java:205)

【问题讨论】:

【参考方案1】:

我找到了解决这个问题的方法,反正有点难看。我只是在 onResume 而不是 onNewIntent 中切换选项卡:

    @Override
    public void onResume() 
        super.onResume();
        if(switchToTab)
            bar.setSelectedNavigationItem(Utils.ORDER_STATUS_TAB_ID);
            switchToTab = false;
        
     

在 onNewIntent() 中,我只设置了 switchToTab = true。我希望有人会提出更好的解决方案。

【讨论】:

我遇到了同样的问题。我正在努力破解 ActionBar.TabListener 实现,添加一个 ft.commitAllowingStateLoss(),但是 Sharlock 它自己也会调用 ft.commit(),它不能被提交两次。我也在***.com/a/10261438/245345 尝试了答案,但它无济于事。最后我找到了你的解决方案,效果很好。谢谢。【参考方案2】:

我认为你不应该在 onTabSelected 方法中调用 commit。框架已经完成了。

哦,使用您收到的交易,不要创建新的。

 public void onTabSelected(Tab tab, FragmentTransaction ft) 
    //remove the first line
    //ft = activity.getSupportFragmentManager().beginTransaction();
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
    if (mFragment == null) 
        mFragment = Fragment
                .instantiate(activity, mClass.getName(), mArgs);
        ft.add(android.R.id.content, mFragment, tag);
        //not sure about this one
        ft.commit();
     else 
        ft.attach(mFragment);
        //not sure about this one neither
        ft.commit(); // line 56
    

【讨论】:

TabListener 是来自 Google 示例的令牌,所以我认为是正确的。使用我收到的交易是什么意思? 感谢更新,getSupportFragmentManager() 应该支持多个平台(我使用支持库),如果我删除提交/开始事务它在正常情况下工作但仍然给我相同恢复后切换选项卡上的异常。我假设我无法从 onNewIntent 方法执行此操作,因为 FragmentManager 尚未准备好。

以上是关于切换选项卡 onNewIntent 导致 IllegalStateException的主要内容,如果未能解决你的问题,请参考以下文章

切换标签时弹出键盘,破坏一切

切换选项卡的按钮跳过第一个选项卡

mfc 选项卡控制切换选项卡

使用tabview更改选项卡时如何使SwiftUI中的计时器保持触发

Hbuilder MUI选项卡怎么样用js使其切换到指定的TAB

使用关闭按钮切换引导选项卡