【问题标题】:Android fragments created twice on orientation change and reset my variables the second timeAndroid片段在方向更改时创建了两次并第二次重置了我的变量
【发布时间】:2015-02-16 16:26:53
【问题描述】:

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

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

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

我把我的日志贴在下面:

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 包含三个片段

在纵向模式下,片段位于 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>

onCreate from MainActivity 扩展 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 来构建纵向模式的 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

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

比如修改前tab片段的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 您可以在 buildUIPortortrait() 和 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();
        }
    }

构建UILandscape

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

【问题讨论】:

  • 我更新了我的第一篇文章以提供新信息,希望对您有所帮助。 ps:我不理解没有解释的否决票我无法为我的未来职位取得进展。我认为我的问题很清楚,我在发布之前进行了研究。我真的不明白为什么我投了两个反对票。
  • 你找到解决办法了吗?!

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


【解决方案1】:

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

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

希望对你有帮助!!!

【讨论】:

  • 嗨,谢谢你的回答,但如果我用你的想法,我有一个纵向的浏览器,也有横向的。我不希望那样。我想我需要在方向改变时重新创建我的活动,包括片段,因为在横向我没有视图寻呼机,所有片段都在屏幕上可见。 ps:看我的编辑
  • 拜托,你能用我的代码和你的答案给我一个例子吗?我不知道该怎么做,因为我在纵向和横向之间使用不同的布局。我试图使用你的答案,但我没有成功,总是出现“IllegalStateException:无法更改片段的容器 ID”并且代码变得非常困难,你可以看到我的编辑 2
猜你喜欢
  • 2013-04-22
  • 2015-05-24
  • 1970-01-01
  • 1970-01-01
  • 2021-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多