2012-06-20 2 views
2

У меня очень тяжелое время для восстановления после изменения конфигурации с помощью ViewPager.ViewPager: восстановление после изменения конфигурации

Я хочу сохранить текущее положение пейджера, чтобы после изменения конфигурации отображалась одна и та же страница. Для этого я сохраняю pager.getCurrentItem() и восстанавливаю его, используя pager.setCurrentItem. Просто это не работает: setCurrentItem на самом деле пытается воссоздать эту страницу, а не выбирать ее! И это несмотря на то, что страница уже создана.

Теперь я не уверен, что я пропустил что-то при реализации адаптера, который поддерживает его, но есть ли ошибка в setCurrentItem, и когда ViewPager думает, что он полностью сконструирован? Однако, глядя на код этой функции, мне это не имеет смысла; это, кажется, всегда пытается воссоздать страницу, кроме случаев, когда нет никаких элементов на всех:

void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { 
    // these are the only checked that make this method return 
    if (mAdapter == null || mAdapter.getCount() <= 0) { 
     setScrollingCacheEnabled(false); 
     return; 
    } 
    if (!always && mCurItem == item && mItems.size() != 0) { 
     setScrollingCacheEnabled(false); 
     return; 
    } 

    // ... removed some init code 

    mCurItem = item; 
    populate(); 

    // ... 
} 

Как вы можете видеть, populate() всегда вызываются, кроме случаев, когда нет либо никаких элементов вообще, или детали вы уже был выбран выбор. Что дает? Это не имеет смысла для меня.

ответ

3

setCurrentItem фактически пытается воссоздать эту страницу вместо ее выбора! И это несмотря на то, что страница уже создана.

Не совсем, по крайней мере, с точки зрения того, как я читаю код.

Как вы можете видеть, функция populate() всегда вызывается, за исключением случаев, когда вообще нет элементов или элемент, который вы пытаетесь выбрать, уже выбран.

populate() будет вызывать addNewItem(), который вызывает instantiateItem() на PagerAdapter. В FragmentPagerAdapter реализация PagerAdapter будет использовать существующий фрагмент, если он доступен, в противном случае он вызывает getItem(), поэтому вы сами создаете страницу. Итак, если вы используете setRetainInstance(true) с фрагментами вашей страницы, и используете FragmentPagerAdapter, их следует использовать повторно.

FragmentStatePagerAdapter Кажется более сложным, и если вы переворачиваете свои PagerAdapter sans-фрагменты, вам нужно реализовать механизм кеширования.

+0

Привет, Марк, я не использую 'FragmentPagerAdapter'. Означает ли это, что я не могу полагаться на 'instantiateObject', который вызывается только при необходимости, т. Е. Должен ли он кэшировать эти экземпляры сам? – Matthias

+0

@Matthias: 'ViewPager' будет кэшировать материал сам по принципу' setOffscreenPageLimit() ', но AFAIK, который не привыкает к изменениям ориентации. Любое кэширование сверх этого (или переработка) зависит от реализации PagerAdapter. – CommonsWare

+0

Спасибо. Я просто кеширую экземпляры представлений, возвращенные с заводского метода, что делает работу. Тем не менее, я все еще думаю, что это недостаток в системе, что 'instantiateItem' вызывается дважды для каждой страницы, один раз во время фазы макета, а затем снова в' setCurrentItem'. Я не могу представить, что это специально, не имеет никакого смысла. – Matthias

Смежные вопросы