Search code examples
androidandroid-fragmentsscreen-orientationandroid-listfragment

Android dynamic Fragment recreated several times on Screen orientation change, after onclick list selection


I am working on the following tutorial, it has problems : it recreates the fragments after each screen rotation.
I fixed it concerning the TitlesFragment class by adding if(savedInstanceState == null) in QuoteViewerActivity:

mFragmentManager = getFragmentManager();
//ADDED THIS CONDITION
if(savedInstanceState == null){
   FragmentTransaction fragmentTransaction = mFragmentManager
                .beginTransaction();
   fragmentTransaction.add(R.id.title_fragment_container, mTitlesFragment);
   fragmentTransaction.commit();
}

it fixed it for Fragment TitlesFragment however for Fragment QuoteFragment it is still recreating it on each screen orientation change because in this tutorial that fragment is created in an onclick event:

@Override
public void onListSelection(int index) {
  if (!mDetailsFragment.isAdded()) {
   FragmentTransaction fragmentTransaction = mFragmentManager
    .beginTransaction();
   fragmentTransaction.add(R.id.quote_fragment_container, mDetailsFragment);
   fragmentTransaction.addToBackStack(null);
   fragmentTransaction.commit();
   mFragmentManager.executePendingTransactions();
  }
  if (mDetailsFragment.getShownIndex() != index) {
     mDetailsFragment.showIndex(index);
  }
}

note that setRetainInstance(true) is set in both fragment's onCreate().

I tried to add this checking but it didn't fix it:

@Override
public void onListSelection(int index) {

  //ADDED THE FOLLOWING TWO LINES
     Fragment f = mFragmentManager.findFragmentById(R.id.quote_fragment_container);
     if(f == null)
  //===============================

  if (!mDetailsFragment.isAdded()) {
   FragmentTransaction fragmentTransaction = mFragmentManager
    .beginTransaction();
   fragmentTransaction.add(R.id.quote_fragment_container, mDetailsFragment);
   fragmentTransaction.addToBackStack(null);
   fragmentTransaction.commit();
   mFragmentManager.executePendingTransactions();
  }
  if (mDetailsFragment.getShownIndex() != index) {
     mDetailsFragment.showIndex(index);
  }
}


==> It recreates this Fragment each time I rotate the screen and duplicates existing menus (explained in this snapshot):

output_snapshot

What am I doing wrong and what is the best practice to fix this? thanks!


Solution

  • Solution:

    In this specific tutorial the solution for this problem was solved by:

    • using onSaveInstanceState to store QuoteFragment state to its containing activity
    • Getting/handling the QuoteFragment by checking if it is found in the savedInstanceState

    Here is what I added/changed in the code:

    .....
    private  QuoteFragment mDetailsFragment = new QuoteFragment();//REMOVED final attribute
    ......
    
    //ADDED
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
    
        if(mFragmentManager.findFragmentByTag(quote_fragment_tag)!=null)
            getFragmentManager().putFragment(outState, QuoteFragment.class.getName(), mDetailsFragment);
    }
    
     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TitleArray = getResources().getStringArray(R.array.Titles);
        QuoteArray = getResources().getStringArray(R.array.Quotes);
        setContentView(R.layout.main);
    
        mFragmentManager = getFragmentManager();
    
        // ADDED
        if(savedInstanceState == null){
            FragmentTransaction fragmentTransaction = mFragmentManager
                    .beginTransaction();
            fragmentTransaction.add(R.id.title_fragment_container, mTitlesFragment);
            fragmentTransaction.commit();
    
        }
        else{//ADDED
            mDetailsFragment = (QuoteFragment) getFragmentManager()
                    .getFragment(savedInstanceState, QuoteFragment.class.getName());
           if(mDetailsFragment == null){
                mDetailsFragment = new QuoteFragment();
                mFragmentManager.beginTransaction()
                .add(R.id.quote_fragment_container, mDetailsFragment,quote_fragment_tag)
                .addToBackStack(null)
                .commit();  
                mFragmentManager.executePendingTransactions();
           }
           }
    }
    

    Note:

    in my humble opinion for best practices concerning fragments and config changes on runtime check Google's official tutorial.