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

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

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

но теперь у меня есть странная ошибка: Когда я нахожусь в ландшафте на индексе 5 и поворачиваю устройство, текущая страница ViewPager установлена на 10. Если я поверну его обратно, то окажусь на странице 5. Если я провожу ViewPage сейчас на страницу 10, Methode getItem адаптера никогда не вызывается, и ViewPage показывает мне одно портретное изображение, а не два для ландшафта. Как такое могло случиться? Есть ли кэш в adapter или ViewPager? В onCreate деятельности все создан новый, адаптер, а также данные (только строки с путем) для 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 ответов


можно переопределить данные метода onsaveinstance FragmentActivity() и не вызывать супер.данные метода onsaveinstance() в методе.

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

не используйте mViewPager.setSaveEnabled(false);

это закончилось большим memoryLeak. После каждого изменения ориентации он помещает фрагменты в массив FragmentManager и никогда не очищает его. Так оно идет до над использования памяти 100mb после изменения ориентации много времен. Методом данные метода onsaveinstance лучше я думать.


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

когда экран вращается,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

Edit:
Я, наконец, решил проблему, это причина моего ViewPager добавить после onStart. При запуске в onStart,FragmentManager попытается восстановить состояние фрагментов. Я проследил в FragmentManager, эти код:

com / android / поддержка / поддержка-фрагмент / 24.2.1 / поддержка-фрагмент-24.2.1-источники.Джар!/ android / поддержка / v4 / app / FragmentManager.java

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

я добавляю ViewPager в XML-макет активности, его фиксированный.

счастливое кодирование: D


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

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