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
- MenuFragment contain main menu
- TabFragment contain main table
- CarteFragment contain the map
- 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();
}
}