17

I'm developing an app that basically has an ActionBar. When my app starts, the Activity creates the fragments and attaches them to each tab, so when I switch I get different views.

The problems arise when I try to rotate the device. After some struggle, I noticed that Android automatically recreates the previously added fragments like this:

SummaryFragment.onCreate(Bundle) line: 79   
FragmentManagerImpl.moveToState(Fragment, int, int, int) line: 795  
FragmentManagerImpl.moveToState(int, int, int, boolean) line: 1032  
FragmentManagerImpl.moveToState(int, boolean) line: 1014    
FragmentManagerImpl.dispatchCreate() line: 1761 
DashboardActivity(Activity).onCreate(Bundle) line: 864  
...

and then I recreate the fragments as usual. So I have the "real" fragments that I expect to work correctly and their "hidden" Android-created counterparts that make my app crash. How can I avoid this behavior? I already tried to call setRetainInstance(false) in the SummaryFragment.

Thank you

Blackbelt
  • 156,034
  • 29
  • 297
  • 305
Luke47
  • 1,583
  • 3
  • 11
  • 14

4 Answers4

42

You need to check for a savedInstanceState [edit: in your parent activity], and if it exists, don't create your fragments.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    if (savedInstanceState == null) {
         // Do your oncreate stuff because there is no bundle   
    }
// Do stuff that needs to be done even if there is a saved instance, or do nothing
}
Glenn Slayden
  • 17,543
  • 3
  • 114
  • 108
Barak
  • 16,318
  • 9
  • 52
  • 84
0

If you have the similar ui(no specific layout-land files) for both orientations you can set android:configChanges="keyboardHidden|orientation" to the activity in your manifest file.

If don't provide please the source code where you're adding the fragments to tabs, and I'll try to help you with improvements.

Lucifer
  • 29,392
  • 25
  • 90
  • 143
Orest
  • 1,857
  • 5
  • 19
  • 27
  • Partially solved with your answer. Since most of the drawing is done dynamically, I remove all views and relayout them according to the new orientation. Honestly, I don't think it is a clean solution but I'm unable to prevent the system to wildly create fragments for me... – Luke47 May 17 '12 at 17:32
  • This helped me because I keep forgetting to update my layout-land files after I change the portrait. It's gotten me about 5 times now. – buster Feb 27 '13 at 12:56
  • 3
    Nasty things will happen when plugging the device into a car dock, or to a TV, or any other configuration change: fragments will still be recreated. android:configChanges is evil, unless you really know what you are doing. – personne3000 Nov 10 '14 at 16:02
0

When you create your activity, check to make sure that it doesn't already exist. If it exists, do nothing...Android will recreate it for you.

private void initFragment() {
        FragmentManager fragMgr = getSupportFragmentManager();
        if (fragMgr.findFragmentByTag(LEADERBOARD_FRAG_TAG) != null) { return; }
        frag = new HdrLeaderboardFragment();
        FragmentTransaction ft = fragMgr.beginTransaction();
        ft.replace(R.id.leaderboard_fragment_wrapper, frag, LEADERBOARD_FRAG_TAG);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.commit();
    }
Damian
  • 8,062
  • 4
  • 42
  • 43
  • 1
    Doing so it still adds two fragments... the one I already had (in the way you suggested) plus another one that is literally driving me mad. It would have been so easy to reset the FragmentManager between orientation changes... – Luke47 May 17 '12 at 14:55
0

I am not sure if there is a better solution, but this is what i did in latest program.

When a fragment is created automatically by system on orientation change and if you want to keep track of them in host activity, catch them in host activity's OnAttachFragment() method. And they get the arguments by default, so you can use them to find out which fragment it is.

   public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);
    if (fragment != null) {
        if(fragment.getArguments() != null) {
            switch (fragment.getArguments().getString(ARG_PARAM1)) {
                case FragmentATag:
                    if (myFragmentA != fragment) {
                        myFragmentA = (FragmentA) fragment;
                    }                     
                    break;
                case FragmentBTag:
                    if (myFragmentB != fragment) {
                        myFragmentB = (FragmentB) fragment;
                    }                        
                    break;                  
            }
        }
     }
   }
sKhan
  • 9,694
  • 16
  • 55
  • 53
avil
  • 3
  • 3