-2

So I decide to post here after 1 week of search. I found and try lot of things to solve my problem but i think my problem is something different.

I will try to explain my problem most clearly as possible. I have an application who have 3 fragments, and when i rotate my application all fragments are create twice.

The second time, when my fragments are recreated, variable of class are reseting and it's very annoying when saveInstanceState are not null the first time but the second time is null.

I post you my log below :

02-10 13:20:22.809: I/onAttach(7729): MenuFragment
02-10 13:20:22.822: I/onAttach(7729): MenuFragment
02-10 13:20:22.822: I/onCreateView(7729): MenuFragment
02-10 13:20:22.843: I/onCreateView(7729): MenuFragment
02-10 13:20:22.844: I/onActivityCreated(7729): MenuFragment
02-10 13:20:22.906: I/onActivityCreated(7729): MenuFragment
02-10 13:20:22.922: I/onResume(7729): MenuFragment
02-10 13:20:22.923: I/onResume(7729): MenuFragment
----------------------------------------------------------------------------
02-10 13:20:22.809: I/onAttach(7729): TabFragment
02-10 13:20:22.908: I/onAttach(7729): TabFragment
02-10 13:20:22.900: I/onCreateView(7729): TabFragment
02-10 13:20:22.908: I/onCreateView(7729): TabFragment
02-10 13:20:22.904: I/onActivityCreated(7729): TabFragment
02-10 13:20:22.911: I/onActivityCreated(7729): TabFragment
----------------------------------------------------------------------------
02-10 13:20:22.809: I/onCreate(7729): MainActivity
----------------------------------------------------------------------------
02-10 13:20:22.904: I/OnCreateView(7729): CarteFragment
02-10 13:20:22.906: I/OnCreateView(7729): CarteFragment

For explanation of class

  1. MenuFragment contain main menu
  2. TabFragment contain main table
  3. CarteFragment contain the map
  4. MainActivity is a FragmentActivity who contains the three fragment

In portrait mode fragments are in a viewPager with three tab that looks like the image below

i can't post image because i need 10 reputation so i post the url : http://hpics.li/5abb967

In landscape mode all fragments are visible, and it's possible to hide/show TabFragment and CarteFragment so it's resize automaticaly to take more space.

An other picture to show fragment in landscape: http://hpics.li/667b232

Before post i read lot of things like (sorry for the (http://), i can't post more than 2 links because i need more than 10 reputation:

  • (http://) stackoverflow.com/questions/7223166/oncreate-and-oncreateview-invokes-a-lot-more-than-required-fragments
  • (http://) developer.android.com/training/basics/fragments/fragment-ui.html#AddAtRuntime
  • (http://) stackoverflow.com/questions/12201695/oncreateview-called-multiple-times-working-with-actionbar-and-fragments
  • (http://) stackoverflow.com/questions/12536400/android-listfragment-created-twice
  • ...etc

Now i post a part of my code, if you need more tell me.

This is MainActivity xml in portrait mode :

<?xml version="1.0" encoding="utf-8"?>
<com.appli.harmo.utils.CustomViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/viewpager">
</com.appli.harmo.utils.CustomViewPager>

MainActivity xml in landscape mode :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="horizontal" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:baselineAligned="false"
        android:orientation="vertical" >

        <FrameLayout
            android:id="@+id/tabFragmentLeftTop"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1">
        </FrameLayout>

        <FrameLayout
            android:id="@+id/carteFragmentLeftBottom"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1" >
        </FrameLayout>
    </LinearLayout>

    <FrameLayout
        android:id="@+id/menuDetailsFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">
    </FrameLayout>

</LinearLayout>

onCreate from MainActivity extend FragmentActivity

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("onCreate", "MainActivity");
        setContentView(R.layout.activity_main);

        backButtonClick();

        final ActionBar actionBar = creationAffichageActionBar();

        gestionSession();

        if(getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
            tabFragment = TabFragment.newInstance();
            carteFragment = CarteFragment.newInstance();
            menuFragment = MenuFragment.newInstance();
            buildUIPortrait(actionBar);

        }else{
            if (findViewById(R.id.tabFragmentLeftTop) != null) {
                tabFragment = (TabFragment) getSupportFragmentManager().findFragmentById(R.id.tabFragmentLeftTop);
                if (tabFragment == null) {
                    tabFragment = TabFragment.newInstance();
                    FragmentManager fm = getSupportFragmentManager();
                    FragmentTransaction ft = fm.beginTransaction();
                    ft.replace(R.id.tabFragmentLeftTop, tabFragment);
                    ft.commit();

                }else {
                    tabFragment = TabFragment.newInstance();
                    FragmentManager fm = getSupportFragmentManager();
                    FragmentTransaction ft = fm.beginTransaction();           
                    ft.replace(R.id.tabFragmentLeftTop, tabFragment);
                    ft.commit();
                }
            }

            if (findViewById(R.id.carteFragmentLeftBottom) != null) {
                carteFragment = (CarteFragment) getSupportFragmentManager().findFragmentById(R.id.carteFragmentLeftBottom);
                if (carteFragment == null) {
                    carteFragment = CarteFragment.newInstance();
                    FragmentManager fm = getSupportFragmentManager();
                    FragmentTransaction ft = fm.beginTransaction();
                    ft.replace(R.id.carteFragmentLeftBottom, carteFragment);
                    ft.commit();

                }else {
                    carteFragment = CarteFragment.newInstance();
                    FragmentManager fm = getSupportFragmentManager();
                    FragmentTransaction ft = fm.beginTransaction();           
                    ft.replace(R.id.carteFragmentLeftBottom, carteFragment);
                    ft.commit();
                }
            }

            if (findViewById(R.id.menuDetailsFragment) != null) {
                menuFragment = (MenuFragment) getSupportFragmentManager().findFragmentById(R.id.menuDetailsFragment);
                if (menuFragment == null) {
                    menuFragment = MenuFragment.newInstance();
                    FragmentManager fm = getSupportFragmentManager();
                    FragmentTransaction ft = fm.beginTransaction();
                    ft.replace(R.id.menuDetailsFragment, menuFragment);
                    ft.commit();

                }else {
                    menuFragment = MenuFragment.newInstance();
                    FragmentManager fm = getSupportFragmentManager();
                    FragmentTransaction ft = fm.beginTransaction();           
                    ft.replace(R.id.menuDetailsFragment, menuFragment);
                    ft.commit();
                }
            }
        }

        if(!tabFragment.getListReleveActif().isEmpty())
            mNotifCount = tabFragment.getListReleveActif().size();
    }

Method who call in onCreate from MainActivity to build UI in portrait mod:

private void buildUIPortrait(final ActionBar actionBar) {
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        // Création de l'adapter qui s'occupera de l'affichage de la liste de Fragments
        this.mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager(), tabFragment, carteFragment, menuFragment);

        pager = (ViewPager)findViewById(R.id.viewpager);
        // Affectation de l'adapter au ViewPager
        pager.setAdapter(this.mPagerAdapter);
        pager.setOffscreenPageLimit(3);
        pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {

            @Override
            public void onPageSelected(int position) {
                actionBar.setSelectedNavigationItem(position);                  
            }
        });

        ActionBar.TabListener tabListener = new ActionBar.TabListener() {

            @Override
            public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {

            }

            @Override
            public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
                pager.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {
            }
        };

        for (int i = 0; i < mPagerAdapter.getCount(); i++) {
            actionBar.addTab(actionBar
                    .newTab()
                    .setText(mPagerAdapter.getPageTitle(i))
                    .setTabListener(tabListener));
        }
    }

The ScreenSlidePagerAdapter extends FragmentPagerAdapter

public class ScreenSlidePagerAdapter extends FragmentPagerAdapter {
    private static final int NUM_PAGES = 3;
    private TabFragment tabFragment;

    private CarteFragment carteFragment;

    private MenuFragment menuFragment;

    public ScreenSlidePagerAdapter(FragmentManager fm, TabFragment tabFragment, CarteFragment carteFragment, MenuFragment menuFragment) {
        super(fm);
        this.tabFragment = tabFragment;
        this.carteFragment = carteFragment;
        this.menuFragment = menuFragment;
    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
        case 0:
            return menuFragment;
        case 1:
            return tabFragment;
        case 2:
            return carteFragment;
        default:
            break;
        }
        return null;
    }

    @Override
    public int getCount() {
        return NUM_PAGES;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        String tabLabel = null;
        switch (position) {
        case 0:
            tabLabel = "Menu";
            break;
        case 1:
            tabLabel = "Tableau";
            break;
        case 2:
            tabLabel = "Carte";
            break;
        }

        return tabLabel;
    }

OnCreate and OnCreateView from MenuFragment

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(savedInstanceState != null){
            fragmentBuild = savedInstanceState.getBoolean("fragmentBuild");
            stopAnimation = savedInstanceState.getBoolean("stopAnimation");
            drawPoint = savedInstanceState.getBoolean("drawPoint");
            sameReleve = savedInstanceState.getBoolean("sameReleve");
            listButtonUI = savedInstanceState.getParcelableArrayList("listButtonUI");
            listButtonActif = savedInstanceState.getParcelableArrayList("listButtonActif");
            relevesSelectionnes = savedInstanceState.getParcelableArrayList("relevesSelectionnes");
            currentPosition = savedInstanceState.getParcelable("currentPosition");
            locationActuelle = savedInstanceState.getParcelable("locationActuelle");
        }

    }

    @Override
    public View onCreateView(LayoutInflater _inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.i("onCreateView", "MenuFragment");
        inflater = _inflater;
        return inflater.inflate(R.layout.fragment_menu, container, false);
    }

OnCreate and OnCreateView from TabFragment

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
            if(savedInstanceState != null ) {
                listReleveActif = savedInstanceState.getParcelableArrayList("listReleveActif");
                listReleve = savedInstanceState.getParcelableArrayList("listReleve"); 
                newAdapter = savedInstanceState.getBoolean("newAdapter");
            }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.i("onCreateView", "TabFragment");
        final View fragmentTab = inflater.inflate(R.layout.fragment_tab, container, false);
        fragmentTab.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1));     
        return  fragmentTab;
    }

OnCreate and OnCreateView from CarteFragment

@Override
    public void onCreate(Bundle savedInstanceState) {
        EventBus.getDefault().registerSticky(this);
        if(savedInstanceState != null){
            rivieresVisible = savedInstanceState.getBoolean("rivieresVisible");
            communesVisible = savedInstanceState.getBoolean("communesVisible");
            departementVisible = savedInstanceState.getBoolean("departementVisible");
            nomObjetVectoProche = savedInstanceState.getString("nomObjetVectoProche");
        }
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.i("OnCreateView", "CarteFragment");
        View rootView  = inflater.inflate(R.layout.fragment_carte, container, false);
        LinearLayout layout = (LinearLayout)rootView.findViewById(R.id.mainLayout);
        mapView = new MapView(rootView.getContext(), coucheVectoRoute, getActivity());
        layout.addView(mapView,LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT); 
        return rootView ;
    }

It's finish, sorry for the big block, i would give you all elements possible to guide you.

I hope you can help me.

Bye

PS: I want to apologize if my english is not perfect.

EDIT : -------------------------------------------------------------------------------------------------------------------------

I modify my onCreate method of MainActivity. I follow this link move Android fragment to a different container Can't change container ID of fragment

The problems like resetting fragment variables on the second passage in life cycle method caused by the duplicate call of life cycle fragment method are solve. (And i don't really know why)

For exemple before modification the onCreate method from tab fragment have the second time when she call saveinstanceState to null, and variable can't be set.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
        if(savedInstanceState != null ) {
            listReleveActif = savedInstanceState.getParcelableArrayList("listReleveActif");
            listReleve = savedInstanceState.getParcelableArrayList("listReleve"); 
            newAdapter = savedInstanceState.getBoolean("newAdapter");
        }
}

But i have always my fragment create twice and i don't know why.

Below you can see the new version of onCreate from MainActivity who solve problems

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("onCreate", "MainActivity");
        setContentView(R.layout.activity_main);

        backButtonClick();

        actionBar = creationAffichageActionBar();

        gestionSession();

        if(savedInstanceState != null){
            tabFragment = (TabFragment) getSupportFragmentManager().getFragment(savedInstanceState, TabFragment.class.getName());
            carteFragment = (CarteFragment) getSupportFragmentManager().getFragment(savedInstanceState, CarteFragment.class.getName());
            menuFragment = (MenuFragment) getSupportFragmentManager().getFragment(savedInstanceState, MenuFragment.class.getName());
        }else{
            tabFragment = TabFragment.newInstance();
            carteFragment = CarteFragment.newInstance();
            menuFragment = MenuFragment.newInstance();
        }

        if(savedInstanceState != null && getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
            FragmentManager fm = getSupportFragmentManager();
            FragmentTransaction ft = fm.beginTransaction();
            ft.remove(menuFragment);
            ft.remove(tabFragment);
            ft.remove(carteFragment).commit();
        }

        if(findViewById(R.id.viewpager) != null){
            buildUIPortrait(actionBar);
        }else{
            if (findViewById(R.id.tabFragmentLeftTop) != null) {
                if (tabFragment == null) {
                    tabFragment = TabFragment.newInstance();
                    FragmentManager fm = getSupportFragmentManager();
                    FragmentTransaction ft = fm.beginTransaction();
                    ft.replace(R.id.tabFragmentLeftTop, tabFragment);
                    ft.commit();
                }else {
                    FragmentManager fm = getSupportFragmentManager();
                    fm.beginTransaction().remove(tabFragment).commit();
                    fm.executePendingTransactions();
                    FragmentTransaction ft = fm.beginTransaction();           
                    ft.replace(R.id.tabFragmentLeftTop, tabFragment);
                    ft.commit();
                }
            }

            if (findViewById(R.id.carteFragmentLeftBottom) != null) {
                if (carteFragment == null) {
                    carteFragment = CarteFragment.newInstance();
                    FragmentManager fm = getSupportFragmentManager();
                    FragmentTransaction ft = fm.beginTransaction();
                    ft.replace(R.id.carteFragmentLeftBottom, carteFragment);
                    ft.commit();
                }else {
                    FragmentManager fm = getSupportFragmentManager();
                    fm.beginTransaction().remove(carteFragment).commit();
                    fm.executePendingTransactions();
                    FragmentTransaction ft = fm.beginTransaction();           
                    ft.replace(R.id.carteFragmentLeftBottom, carteFragment);
                    ft.commit();
                }
            }

            if (findViewById(R.id.menuDetailsFragment) != null) {
                if (menuFragment == null) {
                    menuFragment = MenuFragment.newInstance();
                    FragmentManager fm = getSupportFragmentManager();
                    FragmentTransaction ft = fm.beginTransaction();
                    ft.replace(R.id.menuDetailsFragment, menuFragment);
                    ft.commit();
                }else {
                    FragmentManager fm = getSupportFragmentManager();
                    fm.beginTransaction().remove(menuFragment).commit();
                    fm.executePendingTransactions();
                    FragmentTransaction ft = fm.beginTransaction();           
                    ft.replace(R.id.menuDetailsFragment, menuFragment);
                    ft.commit();
                }
            }
        }

        if(!tabFragment.getListReleveActif().isEmpty())
            mNotifCount = tabFragment.getListReleveActif().size();
    }

and the logcat info with duplicate call of life cycle fragment method

2-17 16:00:27.289: I/onCreate(10224): MainActivity

02-17 16:00:27.342: I/OnCreateView(10224): CarteFragment
02-17 16:00:27.372: I/OnCreateView(10224): CarteFragment

02-17 16:00:27.289: I/onAttach(10224): TabFragment
02-17 16:00:27.375: I/onAttach(10224): TabFragment
02-17 16:00:27.334: I/onCreateView(10224): TabFragment
02-17 16:00:27.375: I/onCreateView(10224): TabFragment
02-17 16:00:27.381: I/onActivityCreated(10224): TabFragment
02-17 16:00:27.342: I/onActivityCreated(10224): TabFragment

02-17 16:00:27.289: I/onAttach(10224): MenuFragment
02-17 16:00:27.370: I/onAttach(10224): MenuFragment
02-17 16:00:27.289: I/onCreate(10224): MenuFragment
02-17 16:00:27.370: I/onCreate(10224): MenuFragment
02-17 16:00:27.307: I/onCreateView(10224): MenuFragment
02-17 16:00:27.381: I/onCreateView(10224): MenuFragment
02-17 16:00:27.308: I/onActivityCreated(10224): MenuFragment
02-17 16:00:27.382: I/onActivityCreated(10224): MenuFragment
02-17 16:00:27.394: I/onResume(10224): MenuFragment

EDIT 2 Try answer of KostasMatrix : -------------------------------------------------------------------------------------------------------------------------

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("onCreate", "MainActivity");
        setContentView(R.layout.activity_main);

        backButtonClick();

        actionBar = creationAffichageActionBar();

        tabFragment = TabFragment.newInstance();
        carteFragment = CarteFragment.newInstance();
        menuFragment = MenuFragment.newInstance();

        gestionSession();

        if(findViewById(R.id.viewpager) != null){
            buildUIPortrait();
        }else{
            buildUILandscape();
        }

        if(!tabFragment.getListReleveActif().isEmpty())
            mNotifCount = tabFragment.getListReleveActif().size();
    }

onConfigurationChange you can find just below buildUIPortrait() and buildUILanscape After

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.i("RotationChange", "*************************************************");
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            setContentView(R.layout.activity_main_land);
            buildUILandscape();
        }
        if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            setContentView(R.layout.activity_main);
            buildUIPortrait();
        }
    }

buildUILandscape

private void buildUILandscape() {
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
        if (findViewById(R.id.tabFragmentLeftTop) != null) {
            FragmentManager fm = getSupportFragmentManager();
            fm.beginTransaction().remove(tabFragment).commit();
            fm.executePendingTransactions();
            FragmentTransaction ft = fm.beginTransaction();           
            ft.replace(R.id.tabFragmentLeftTop, tabFragment);
            ft.commit();
        }

        if (findViewById(R.id.carteFragmentLeftBottom) != null) {
            FragmentManager fm = getSupportFragmentManager();
            fm.beginTransaction().remove(carteFragment).commit();
            fm.executePendingTransactions();
            FragmentTransaction ft = fm.beginTransaction();           
            ft.replace(R.id.carteFragmentLeftBottom, carteFragment);
            ft.commit();
        }

        if (findViewById(R.id.menuDetailsFragment) != null) {
            FragmentManager fm = getSupportFragmentManager();
            fm.beginTransaction().remove(menuFragment).commit();
            FragmentTransaction ft = fm.beginTransaction();           
            ft.replace(R.id.menuDetailsFragment, menuFragment);
            ft.commit();
        }
    }
Community
  • 1
  • 1
Slasch
  • 275
  • 1
  • 6
  • 20
  • I updated my first post to provide new information, i hope it help you. ps: i don't understand the down vote without explanation i can't progress for my futur post. I think my problem is clear and i make an research effort before post. I really don't understand why i take two down vote. – Slasch Feb 17 '15 at 15:54
  • have you find any solution ?! – Muhammad Naderi Feb 02 '16 at 14:13

1 Answers1

-1

If you dont want your activity including the fragments not be recreated while the orieantation changes just go to your manifest file and add this line where you create the activity that hosts the fragments:

android:configChanges="orientation|keyboardHidden|screenSize"

You can make whatever changes you want by overriding this method

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            //do your stuff
        }
        if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {

            //do your stuff
        }
    }

Hope it helps!!!

Kostas Drak
  • 3,222
  • 6
  • 28
  • 60
  • Hi, thx for your answer, but if i use your idea i have a viewpager in portrait but also in landscape. And i don't want that. I think i need my activity including the fragments be recreated while the orientation changes, because, in landscape i don't have view pager, all fragments are visible in the screen. Ps: see my edit – Slasch Feb 23 '15 at 08:46
  • Please, can you give me an example using my code and using your answers ? I don't see how can i do that as i use different layout between portrait and landscape. I trying to use your answers, but I have not succeeded, always had "IllegalStateException: Can't change container ID of Fragment" and the code become really hard, you can see my edit 2 – Slasch Feb 27 '15 at 10:30