Android片段在方向更改时创建两次,并在第二次重置我的变量

时间:2015-02-16 16:26:53

标签: android android-activity android-fragments android-actionbar fragment

所以我决定在搜索一周后在这里发帖。我发现并尝试了很多东西来解决我的问题,但我认为我的问题是不同的。

我会尽可能清楚地解释我的问题。我有一个有3个片段的应用程序,当我旋转我的应用程序时所有片段都会创建两次。

第二次,当我的片段被重新创建时,类的变量正在重置,当saveInstanceState第一次不为null但第二次为null时,它非常烦人。

我在下面发给你的日志:

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

关于班级的解释

  1. MenuFragment包含主菜单
  2. TabFragment包含主表
  3. CarteFragment包含地图
  4. MainActivity是一个FragmentActivity,包含三个片段
  5. 在纵向模式下,片段位于viewPager中,其中有三个选项卡,如下图所示

    我无法发布图片,因为我需要10个声誉,所以我发布了网址:http://hpics.li/5abb967

    在横向模式下,所有片段都是可见的,并且可以隐藏/显示TabFragment和CarteFragment,以便自动调整大小以占用更多空间。

    另一张在风景中显示片段的图片:http://hpics.li/667b232

    发布之前我读了很多像(对不起(http://),我不能发布2个以上的链接,因为我需要10个以上的声誉:

    • (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
    • ...等

    现在我发布我的部分代码,如果你需要更多告诉我。

    这是纵向模式下的MainActivity xml:

    <?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:

    <?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>
    
    来自MainActivity的

    onCreate扩展了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();
        }
    

    从MainActivity调用onCreate以在纵向mod中构建UI的方法:

    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));
            }
        }
    

    ScreenSlidePagerAdapter扩展了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;
        }
    

    来自MenuFragment的OnCreate和OnCreateView

    @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);
        }
    

    TabFragment的OnCreate和OnCreateView

    @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;
        }
    

    来自CarteFragment的OnCreate和OnCreateView

    @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 ;
        }
    

    结束了,对不起,我会给你所有可能的元素来指导你。

    我希望你能帮助我。

    再见

    PS:如果我的英语不完美,我想道歉。

    编辑:------------------------------------------ -------------------------------------------------- -----------------------------

    我修改了MainActivity的onCreate方法。我点这个链接move Android fragment to a different container Can't change container ID of fragment

    解决了生命周期片段方法重复调用引起的生命周期方法中第二段重置片段变量等问题。 (而且我不知道为什么)

    例如,在修改之前,选项卡片段中的onCreate方法第二次将saveinstanceState调用为null,并且无法设置变量。

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

    但我总是我的片段创建两次,我不知道为什么

    您可以在下面看到MainActivity中解决问题的新版onCreate

    @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();
        }
    

    和生命周期片段方法重复调用的logcat信息

    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
    

    编辑2尝试回答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你可以在buildUIPortrait()和buildUILanscape之后找到

    @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();
            }
        }
    

1 个答案:

答案 0 :(得分:-1)

如果您不希望在orieantation更改时重新创建包含片段的活动,只需转到清单文件并在创建托管片段的活动的位置添加此行:

android:configChanges="orientation|keyboardHidden|screenSize"

您可以通过覆盖此方法进行任何所需的更改

    @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
        }
    }

希望它有所帮助!!!