简体   繁体   English

Android onConfigurationChanged:如何保存和还原片段回栈?

[英]Android onConfigurationChanged: how to save and restore fragment back stack?

I have an activity with a dual pane: a list of menu items on the left (fragment M) and details of the currently selected item on the right (fragment D). 我有一个带有双窗格的活动:左侧的菜单项列表(片段M),右侧的当前所选项目的详细信息(片段D)。

When the user selects an item in fragment D, fragment D gets replaced with another fragment (let's call it D1). 当用户在片段D中选择一个项目时,片段D被另一个片段替换(我们称其为D1)。 When the user selects an item in fragment D1, fragment D1 gets replaced with another fragment (let's call it D2), and so on. 当用户在片段D1中选择一个项目时,片段D1被另一个片段替换(我们称其为D2),依此类推。 Of course, when the user presses the back button she can go back in the fragments history: D2->D1->D. 当然,当用户按下“后退”按钮时,她可以返回片段历史记录:D2-> D1-> D。

My problem is: how can I save and restore the full fragment back stack upon configuration change (in particular, upon screen orientation)? 我的问题是:如何在配置更改时(尤其是在屏幕方向上)保存和还原完整的片段回栈?

It seems very strange to me that no one else had had this problem before, but I did not find anything about this during my searches on Google and Stack Overflow. 对我来说,很奇怪,以前没有人遇到过这个问题,但是在Google和Stack Overflow上搜索期间,我什么都没找到。 If I missed any relevant post, please address me to it. 如果我错过任何相关的帖子,请给我发邮件。

I know that I could simply add the android:configChanges="orientation|screenSize" attribute to my activity to avoid activity recreation, but I simply cannot do that. 我知道我可以简单地将android:configChanges="orientation|screenSize"属性添加到我的活动中以避免活动重新创建,但是我根本做不到。

The reason I cannot do that is that I am using Action Bar Sherlock (vers. 4) for backward compatibility and that component needs activity recreation to behave correctly upon configuration change, AFAIK. 我之所以不能这样做,是因为我正在使用Action Bar Sherlock(第4版)以实现向后兼容性,并且该组件需要重新激活活动才能在配置更改AAFIK后正确运行。

If there is another way to recreate the Action Bar Sherlock component without destroying and re-creating the activity please let me know. 如果还有另一种方法可以重新创建Action Bar Sherlock组件,而又不破坏并重新创建活动,请告诉我。

Thanks in advance. 提前致谢。

I was able to do this by caching the Fragments as I added them in my own ArrayList. 通过将片段添加到自己的ArrayList中,我可以通过缓存这些片段来实现此目的。 Then I set up an OnBackStackChangedListener to keep track of which one was shown and pop off the ArrayList as necessary. 然后,我设置了一个OnBackStackChangedListener来跟踪显示了哪个,并根据需要弹出ArrayList。

My purpose was a little different but the code below should be what you need for what you describe. 我的目的有些不同,但是下面的代码应该是您描述的内容。 The tags are so you can have multiple back stacks if you need. 标签是这样,因此您可以根据需要具有多个后置堆栈。 It won't compile as-is (I've clipped lots of my own code) but should give you an idea of how I did it. 它不会按原样编译(我已经裁剪了很多自己的代码),但是应该让您了解我是如何做到的。 Additional disclaimer: I just got this working and there may be issues I haven't hit yet. 附加免责声明:我刚刚开始工作,可能还有一些尚未解决的问题。

   public void replaceFragmentWithBackStackForTag(Fragment fragment, String tag)
   {
      FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
      ft.detach(visibleFragment);
      ft.add(R.id.realtabcontent, fragment, tag);
      ft.attach(fragment);
      ft.addToBackStack(null);
      manualBackStacks.get(tag).add(fragment);
      ft.commit();
      this.getSupportFragmentManager().executePendingTransactions();
   }

The code you'll want where your activity gets recreated after an orientation change: 更改方向后,您需要在哪里重新创建活动的代码:

 ArrayList<Fragment> backStack =
       new ArrayList<Fragment>(manualBackStacks.get(tag));
 popArrayListToIndex(manualBackStacks.get(tag), 0); // helper I wrote
 for (int bs = 1; bs < backStack.size(); bs++) {
    replaceFragmentWithBackStackForTag(backStack.get(bs), tag);
 }

The backstack listener: 堆栈监听器:

 public void onBackStackChanged() {
    int index = getSupportFragmentManager().getBackStackEntryCount();
    ArrayList<Fragment> backStack = manualBackStacks.get(tag);
    visibleFragment = backStack.get(index);
    // Pop the last element if we've backed up.
    popArrayListToIndex(backStack, index);
 }

Hope this helps. 希望这可以帮助。

Action Bar Sherlock (ABS) needed to recreate the action bar as part of recreating the activity in ABS 3.x, but according to @ Jake Wharton's comment , version 4 does not need recreation--it can handle orientation changes. Action Bar Sherlock(ABS)需要重新创建操作栏,这是在ABS 3.x中重新创建活动的一部分,但是根据@ Jake Wharton的评论 ,版本4不需要重新创建-它可以处理方向更改。 So, set android:configChanges="orientation" and your fragment back stack will persist. 因此,设置android:configChanges =“ orientation”,您的片段回栈将继续存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM