FragmentManager не вызывает onCreateView со второй вкладкой после изменения ориентации

У меня есть 3 фрагмента в TabA и PreferenceFragment в TabB. Чтобы воссоздать проблему, я запускаю программу, TabA отображается нормально. Я нажимаю TabB, и он также отображается нормально. Если я вернусь к TabA и изменю ориентацию, в следующий раз, когда я нажму на TabB, будет просто пустой экран. Я сузил его до того, что FragmentManager не вызывает onCreateView для фрагмента в TabB.

Я проверяю, что фрагменты не являются нулевыми и их не нужно воссоздавать, и получаю ссылки на них с их findFragmentByTag после изменения ориентации. У TabA никогда не было проблем, я пытался воссоздать проблему с TabA, но onCreateView всегда вызывал FragmentManager для каждого фрагмента. У меня минимальный API 15, цель 19.

Урезанная версия MyActivity.java для запуска

public class MyActivity extends Activity {
    private static final String TAG = "MainActivity";
    public FragmentManager fm;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_master);

        fm = getFragmentManager();

        final ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        ActionBar.Tab tabA = actionBar.newTab().setText("Main");
        ActionBar.Tab tabB = actionBar.newTab().setText("Settings");

        tabA.setTabListener(new TabAListener(this));
        actionBar.addTab(tabA);

        tabB.setTabListener(new TabBListener(this));
        actionBar.addTab(tabB);

        if (savedInstanceState != null) {
            int index = savedInstanceState.getInt("index");
            actionBar.setSelectedNavigationItem(index);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        Log.d(TAG, "onSaveInstanceState");
        super.onSaveInstanceState(outState);
        int i = getActionBar().getSelectedNavigationIndex();
        outState.putInt("index", i);
    }

    public class TabAListener implements ActionBar.TabListener {

        private static final String genTag = "GenerateFragment";
        private static final String aboutTag = "AboutFragment";
        public static final String resultsTag = "ResultsListFragment";

        private ArrayList<Fragment> fragList;

        public TabAListener(Activity activity) {
            fragList = null;
        }

        public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
            // Reselected don't do anything
            Log.d(TAG, "Tab A: on Tab reselected");
        }

        public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
            Log.d(TAG, "Tab A: on Tab Selected");

            // attach all the fragments
            if (fragList == null) {
                fragList = new ArrayList<Fragment>();

                TestFragment genFrag;
                if (fm.findFragmentByTag(genTag) == null) {
                    genFrag = new TestFragment();
                    ft.add(R.id.gen_fragment, genFrag, genTag);
                } else genFrag = (TestFragment) fm.findFragmentByTag(genTag);
                TestFragment aboutFrag;
                if (fm.findFragmentByTag(aboutTag) == null) {
                    aboutFrag = new TestFragment();
                    ft.add(R.id.about_fragment, aboutFrag, aboutTag);
                } else aboutFrag = (TestFragment) fm.findFragmentByTag(aboutTag);
                TestFragment resultsFrag;
                if (fm.findFragmentByTag(resultsTag) == null) {
                    resultsFrag = new TestFragment();
                    ft.add(R.id.results_fragment, resultsFrag, resultsTag);
                } else {
                    resultsFrag = (TestFragment) fm.findFragmentByTag(resultsTag);
                }


                fragList.add(genFrag);
                fragList.add(aboutFrag);
                fragList.add(resultsFrag);
                Log.d(TAG, "Tab A: Added fragments to the ArrayList");

            } else {

                Iterator iter = fragList.iterator();

                while (iter.hasNext()) {
                    Log.d(TAG, "Tab A: Attaching fragments");
                    ft.attach((Fragment) iter.next());
                }
            }
        }

        public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
            Log.d(TAG, "Tab A: on Tab Unselected");

            if (fragList != null) {
                Iterator iter = fragList.iterator();
                while (iter.hasNext()) {
                    Log.d(TAG, "Tab A: Fragments detached");
                    ft.detach((Fragment) iter.next());
                }
            }
        }
    }

    public class TabBListener implements ActionBar.TabListener {

        private static final String settingsTag = "SettingsFragment";

        private ArrayList<Fragment> fragList;

        public TabBListener(Activity activity) {
            fragList = null;
        }

        public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
            // Reselected don't do anything
            Log.d(TAG, "Tab B: on Tab reselected");
        }

        public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {

            Log.d(TAG, "Tab B: on Tab Selected");
            // attach all the fragments
            if (fragList == null) {

                fragList = new ArrayList<Fragment>();
                TestFragment settingsFrag;
                if (fm.findFragmentByTag(settingsTag) == null) {
                    settingsFrag = new TestFragment();
                    ft.add(R.id.frame_main, settingsFrag, settingsTag);
                } else {
                    Log.d(TAG, "Tab B: not null");
                    settingsFrag = (TestFragment) fm.findFragmentByTag(settingsTag);
                }

                fragList.add(settingsFrag);
                Log.d(TAG, "Tab B: Added fragments to the ArrayList");

            } else {

                Iterator iter = fragList.iterator();
                while (iter.hasNext()) {
                    Log.d(TAG, "Tab B: Attaching fragments");
                    ft.attach((Fragment) iter.next());
                }
            }
        }

        public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
            Log.d(TAG, "Tab B: on Tab Unselected");

            if (fragList != null) {
                Iterator iter = fragList.iterator();
                while (iter.hasNext()) {
                    Log.d(TAG, "Tab B: Fragments detached");
                    ft.detach((Fragment) iter.next());
                }
            }
        }
    }

    public static class TestFragment extends Fragment {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRetainInstance(true);
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            super.onCreateView(inflater, container, savedInstanceState);
            return inflater.inflate(R.layout.fragment_text, container, false);
        }
    }

}

activity_master.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/frame_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <LinearLayout
            android:layout_width="0dip"
            android:layout_height="match_parent"
            android:layout_weight="3"
            android:orientation="vertical">

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

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

        <FrameLayout
            android:id="@+id/results_fragment"
            android:layout_width="0dip"
            android:layout_height="match_parent"
            android:layout_weight="2" />
    </LinearLayout>
</FrameLayout>

фрагмент_текст.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="test" />
</LinearLayout>

person AMichael    schedule 04.07.2014    source источник


Ответы (1)


Итак, я думаю, мне нужно удалить супервызов в MainActivity.onSaveInstanceState, чтобы onCreateView правильно вызывался для фрагмента TabB после изменения ориентации. Хм, я не уверен, почему это работает, может кто-нибудь объяснить, почему?

Мне удалось выяснить, что super.onSaveInstanceState сохраняет представления действий, когда пользователь уходит из приложения и в конечном итоге возвращается. И FragmentManager также несет ответственность за содержимое фрагмента посредством изменения ориентации. Я немного потерян в этот момент.

person AMichael    schedule 05.07.2014