1

I have an app, with to layouts. In portrait i have one frag on screen, in land - two.

In OnCreate of my Activity:

frameDetailsFragment = (FrameLayout) findViewById(R.id.detailsFragment);

    if (frameDetailsFragment != null){
        if (EntryPool.getPool(this).getEntries().size() > 0) {
            detailsFragment = DetailsFragment.newInstance(EntryPool.getPool(this).getEntries().get(0));

            getFragmentManager().beginTransaction()
                    .add(R.id.detailsFragment, detailsFragment, DETAILS_FRAGMENT)
                    .commit();
        }
    }

So when we are in portrait we do not create DetailsFragment. In DetailsFragment there is nothing interesting, no setRetainState, and i do not save activity in onAtach(). I just log out lifecycle methods. So, When i launch app in portarit, it works (Details frag is not created). then i rotate - Details frag is crated. Then I rotate again - and I see this:

  04-22 12:06:42.737    2692    2692    I   ANT DetailsFragment :: onDestroy
  04-22 12:06:42.737    2692    2692    I   ANT DetailsFragment :: onDetach
  04-22 12:06:42.761    2692    2692    I   ANT DetailsFragment :: onAttach
  04-22 12:06:42.761    2692    2692    I   ANT DetailsFragment :: onCreate
  04-22 12:06:42.805    2692    2692    D   ANT MainActivity oncretae
  04-22 12:06:42.845    2692    2692    I   ANT DetailsFragment :: onCreateView
  04-22 12:06:42.857    2692    2692    I   ANT DetailsFragment :: onActivityCreated

As wee can see, frag recretaed bu fragment manager. WHY? Plese help me, I can not see any logic in this behavior - I did not wrotye setRetainInstanse, nor addToBackState when performing add fragment transaction

Anton Kizema
  • 1,072
  • 3
  • 13
  • 27

4 Answers4

1

Since your question is why this is happening, (and other answers are about how to stop it):

This occurs because the Activity doesn't know when it is restoring the Fragment from the saved instance state that the Fragment is no longer needed. If, after the activity has restored the view hierarchy there is a view with the same id as what the Fragment was originally added to (the first parameter in the transaction.add) then it will be re-added after the rotation change.

FunkTheMonk
  • 10,908
  • 1
  • 31
  • 37
  • Seems like that, exactly. And if there is any good method to set behavior, that my fragment would not be saved in onSaveInstanceState and recreated, if not needed? – Anton Kizema Apr 23 '15 at 11:21
0

Add code below in manifest file where you declare activity from which you are calling fragment:

android:configChanges="keyboardHidden|orientation|screenSize"
Rahul Sharma
  • 5,949
  • 5
  • 36
  • 46
0

You should setRetainInstance to true in your fragment

public void setRetainInstance (boolean retain)

Control whether a fragment instance is retained across Activity re-creation (such as from a configuration change). This can only be used with fragments not in the back stack. If set, the fragment lifecycle will be slightly different when an activity is recreated:

onDestroy() will not be called (but onDetach() still will be, because the fragment is being detached from its current activity). onCreate(Bundle) will not be called since the fragment is not being re-created. onAttach(Activity) and onActivityCreated(Bundle) will still be called.

Bojan Kseneman
  • 15,488
  • 2
  • 54
  • 59
  • Yes, but still fragment would be recreated in portrait mode (or Reatached, if setRetainInstance true), even if i do not need it. – Anton Kizema Apr 23 '15 at 10:19
0

I decided this problem folowing way - In OnSaveInstance state I simply remove fragment with my fragment manager, if it exists :

   @Override
protected void onSaveInstanceState(Bundle outState) {
    if (detailsFragment != null) {
        getFragmentManager().beginTransaction()
                .remove(detailsFragment)
                .commit();
    }

    super.onSaveInstanceState(outState);
}

With the help of this hook, that fragment is cretaed again in Activity only if it will pass the check in onCreate:

   if (frameDetailsFragment != null){
    if (EntryPool.getPool(this).getEntries().size() > 0) {
        detailsFragment = DetailsFragment.newInstance(EntryPool.getPool(this).getEntries().get(0));

        getFragmentManager().beginTransaction()
                .add(R.id.detailsFragment, detailsFragment, DETAILS_FRAGMENT)
                .commit();
    }

But for sure there has to be better solution, wich enforce fragment to be desrtoyed, detasched, and never recreted, only if it will be called from onCreate

Anton Kizema
  • 1,072
  • 3
  • 13
  • 27
  • Or even better solution - http://stackoverflow.com/questions/15496362/handle-fragment-duplication-on-screen-rotate-with-sample-code?nah=29859034#29859034 – Anton Kizema Apr 24 '15 at 23:16