ViewPager + FragmentStatePagerAdapter + изменение ориентации

У меня есть небольшая проблема: у меня есть ViewPager с некоторыми страницами, и я использую FragmentStatePagerAdapter для обработки данных. В портретном режиме у меня есть, например, 20 страниц для ViewPager, а в альбомной ориентации у меня всего 10 страниц для ViewPager. Поэтому при изменении ориентации я создаю новый адаптер с другими данными.

Вот небольшое объяснение, почему: я показываю одно изображение в портретной и два в альбомной, но всегда все в счет. Если у меня есть 10 фотографий, чтобы показать, у меня есть 10 в портретной и 5 в альбомной (всегда две).

Но теперь у меня странная ошибка: когда я нахожусь в альбомной ориентации с индексом 5 и поворачиваю устройство, текущая страница ViewPager устанавливается на 10. Если я снова включаю его, я нахожусь на странице 5. Если я проведу ViewPage сейчас на страницу 10 метод getItem адаптера никогда не вызывается, и ViewPage показывает мне одно портретное изображение, а не два для альбомной ориентации. Как это может случиться? Есть ли кеш в адаптере или ViewPager? В onCreate of Activity все заново создано, адаптер, а также данные (только строки с путем) для ViewPager. Так есть идеи, как исправить эту действительно страшную "особенность"?

Вот некоторый код:

OnCreate:

    mViewPagerAdapter = new ReaderPageViewAdapter(getSupportFragmentManager(), getBaseContext(), mCurrentDocument.mPages, getResources()
                .getConfiguration().orientation);
    mPageReader = (ReaderViewPager) findViewById(R.id.pager);
    mPageReader.setAdapter(mViewPagerAdapter);

адаптер getItem:

    public Fragment getItem(final int index) {
        final PageInfo pageInfo = mPages.get(index);
        final PageFragment pageFragment = (PageFragment) PageFragment
                .instantiate(mContext, pageInfo.mClss.getName(), pageInfo.mArgs);
        return pageFragment;
    }

Если вам нужно что-то еще, просто скажите мне. Спасибо

3 ответа

Решение

Вы можете переопределить FragmentActivity для onSaveInstanceState() и не вызывать super.onSaveInstanceState() в методе.

@Override
protected void onSaveInstanceState(final Bundle outState) {
    // super.onSaveInstanceState(outState);
}

Не использовать mViewPager.setSaveEnabled(false);

это закончилось большой утечкой памяти. После каждого изменения ориентации он помещает фрагменты в массив FragmentManager и никогда не очищает его. Таким образом, после многократного изменения ориентации использование памяти превышает 100 МБ. Я думаю, что использование метода onSaveInstanceState - лучший способ.

У меня тоже возникла эта проблема и я нашел причину.

Когда-либо экран вращался, FragmentManager сохранит все ваши фрагменты активности, не удалит фрагменты при использовании FragmentStatePagerAdapter, Ты можешь использовать FragmentManager.getFragments() проверить количество фрагментов.

Пример: у действия есть 4 фрагмента, после 4-кратного изменения ориентации, список FragmentManager.getFragments() размер будет 20!

Я нашел несколько решений:

  1. Не звоните super.onSaveInstanceState() из вас активность, но это, кажется, не очень хорошее решение, фрагменты не могут сохранить состояние и восстановить.

  2. использование FragmentPagerAdapter вместо FragmentStatePagerAdapter, Но после ориентации изменились, фрагменты которых ViewPager hosted был пустым (У кого-нибудь еще есть такая же проблема?). Но я могу удалить все фрагменты в Activity.onCreate починить это. как это:

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FragmentManager fm = getSupportFragmentManager();
        List<Fragment> fragments = fm.getFragments();
        if (fragments != null) {
            FragmentTransaction transaction = fm.beginTransaction();
            for (Fragment fragment : fragments) {
                transaction.detach(fragment).remove(fragment);
            }
            transaction.commitNowAllowingStateLoss();
        }
        ...
    

    Но Fragment.onCreateView() звонил дважды.

Я все еще ищу идеальное решение:D

Редактировать:
Я наконец решил проблему, это потому, что мой ViewPager добавить после OnStart. Когда запустить на OnStart, FragmentManager постараюсь восстановить фрагменты состояния. Я проследил в FragmentManagerИметь этот код:

ком / Android/ поддержка / поддержка осколок /24.2.1/ поддержка осколок-24.2.1-sources.jar!/android/support/v4/app/FragmentManager.java

Проверьте выделенную линию, f.mContainerId на самом деле мой идентификатор ViewPager. Затем он попытается добавить представление фрагментов в ViewPager. В моем случае ViewPager еще не добавлен, поэтому он будет очищен, но состояние фрагментов ATTACHED, И в FragmentPagerAdapter.instantiateItem(), Если фрагмент был добавлен, это просто сделать attach фрагмент, но фрагмент уже прикреплен, так что его ничего не делать:(

Я добавляю ViewPager в макет активности XML, это исправлено.

Удачного кодирования:D

Просто вы используете в viewPager.setonpagechangelistener и реализуете для кода приложения применять ваше приложение,

http://developer.android.com/reference/android/support/v4/view/ViewPager.html

Другие вопросы по тегам