Handle Fragment duplication on Screen Rotate (with sample code)

后端 未结 4 1929
死守一世寂寞
死守一世寂寞 2021-02-06 11:03

There are some similar answers, but not to this situation.


My situation is simple.

I have an Activity with two different layouts, one in Portrait,

4条回答
  •  情书的邮戳
    2021-02-06 11:09

    @midnite ,first of all thanks for your question, I had the same question, on wich I worked for days. Now I wound some tricky resolution to this problem - and want to share this to community. But If someone has better solution, please write in comments.

    So, I have same situation - different layouts for two device orientation. In portrait there is no need for DetailsFragment.

    I simply in OnCreate trying to find already created fragments:

        fragment = (ToDoListFragment) getFragmentManager().findFragmentByTag(LISTFRAGMENT);
        frameDetailsFragment = (FrameLayout) findViewById(R.id.detailsFragment);
        detailsFragment = (DetailsFragment) getFragmentManager().findFragmentByTag(DETAILS_FRAGMENT);
        settingsFragment = (SettingsFragment) getFragmentManager().findFragmentByTag(SETTINGS_FRAGMENT);
    

    Right after that I am adding my main fragment -

        if (fragment == null){
            fragment = new ToDoListFragment();
            getFragmentManager().beginTransaction()
                    .add(R.id.container, fragment, LISTFRAGMENT)
                    .commit();
        }
    

    And clear back stask of my fragments:

      if (getFragmentManager().getBackStackEntryCount() > 0 ) {
            getFragmentManager().popBackStackImmediate();
        }
    

    And the MOST interesting is here -

      destroyTmpFragments();
    

    Here is the method itself:

      private void destroyTmpFragments(){
        if (detailsFragment != null && !detailsFragment.isVisible()) {
            Log.d("ANT", "detailsFragment != null, Destroying");
            getFragmentManager().beginTransaction()
                    .remove(detailsFragment)
                    .commit();
    
            detailsFragment = null;
        }
    
        if (settingsFragment != null && !settingsFragment.isVisible()) {
            Log.d("ANT", "settingsFragment != null, Destroying");
            getFragmentManager().beginTransaction()
                    .remove(settingsFragment)
                    .commit();
    
            settingsFragment = null;
        }
    }
    

    As you can see, I clean manually all fragments, that FragmentManager gentfully saved for me (great thanks to him). In log I have next lifecycle calls:

     04-24 23:03:27.164 3204    3204    D   ANT MainActivity onCreate()
     04-24 23:03:27.184 3204    3204    I   ANT DetailsFragment :: onCreateView
     04-24 23:03:27.204 3204    3204    I   ANT DetailsFragment :: onActivityCreated
     04-24 23:03:27.204 3204    3204    I   ANT DetailsFragment :: onDestroy
     04-24 23:03:27.208 3204    3204    I   ANT DetailsFragment :: onDetach
    

    So in onActivityCreated make your views check for null - in case fragment is not visible. It will be deleted little bit later (It is so maybe cuz fragment manager's remove is async) After, in activity's code we can create brand new Fragment instance, with proper layout (fargmnet's placeholder) and fragment will be able to find it's views for example, and will not produce NullPointerException

    But, fragments that are in back stack are deleted pretty fast, without call to onActivityCreated (with th help of above code:

     if (getFragmentManager().getBackStackEntryCount() > 0 ) {
            getFragmentManager().popBackStackImmediate();
        }
    

    At last, at the end i add fragment if I am in land orientation -

     if (frameDetailsFragment != null){
            Log.i("ANT", "frameDetailsFragment != null");
    
            if (EntryPool.getPool().getEntries().size() > 0) {
                if (detailsFragment == null) {
                    detailsFragment = DetailsFragment.newInstance(EntryPool.getPool().getEntries().get(0), 0);
                }
    
                getFragmentManager().beginTransaction()
                        .replace(R.id.detailsFragment, detailsFragment, DETAILS_FRAGMENT)
                        .commit();
            }
        }
    

提交回复
热议问题