Android onConfigurationChanged: how to save and restore fragment back stack?
Asked Answered
F

2

8

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).

When the user selects an item in fragment D, fragment D gets replaced with another fragment (let's call it 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. Of course, when the user presses the back button she can go back in the fragments history: 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. 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.

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.

If there is another way to recreate the Action Bar Sherlock component without destroying and re-creating the activity please let me know.

Thanks in advance.

Fitz answered 3/4, 2012 at 18:45 Comment(0)
V
5

I was able to do this by caching the Fragments as I added them in my own ArrayList. Then I set up an OnBackStackChangedListener to keep track of which one was shown and pop off the ArrayList as necessary.

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.

Voice answered 6/4, 2012 at 3:13 Comment(1)
I'm very interested in this approach, but I don't feel that your answer gives enough detail for me to easily understand. can you add more detail to your answer?Raddatz
S
0

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. So, set android:configChanges="orientation" and your fragment back stack will persist.

Sharpeared answered 3/4, 2012 at 23:24 Comment(1)
@Iarham1 Thanks for your reply, but, unfortunately, ABS 4 still has some issues on some OS versions (e.g. 2.3.7) when android:configChanges="orientation" is set, as described in issue #279, so this is not a viable solution, at present. I hope that Jake Wharton will fix it in the near future, but, in the meantime, do you or anyone else know how to save and restore the full fragment back stack upon configuration change? Or alternatively how to tweak ABS code to programmatically recreate only ABS on config change?Fitz

© 2022 - 2024 — McMap. All rights reserved.