Задать вопрос
we_love_russia
@we_love_russia
Основатель Meanwhile

Как сделать бесконечный ViewPager с тремя элементами в Android?

Задача — реализовать «бесконечную» прокрутку страниц с использованием ViewPager и PagerAdapter. В качестве элементов выступают View (не Fragment). Все view создаются из единого xml-layout через inflater, отличаются лишь содержанием. Содержание подгружается из API.


В параметрах ViewPager установил ограничение на лимит неактивных страниц слева и справа:

mViewPager.setOffscreenPageLimit(1);


Т.о., одновременно могут храниться 1 активная страница и по 1 слева и справа, в случае если их становится больше, вызывается соотв. метод на удаление в PagerAdapter-e. При запуске имеется 1 id, для которого загружается содержание из Интернета с API (картинка + текст). После загрузки первой страницы апи присылает ответ с id следующей страницы, если таковая имеется. id-шники страниц храню в ArrayList: при создании адаптера инициализирую этот список первым значением (id начальной страницы), при получении следующего id добавляю туда следующее значение. Получается, при запуске у меня имеется адаптер, getCount которого возвращает размер этого массива id (mPagesId), в начале он равен 1. Далее адаптер запрашивает 0-вую позицию для ViewPager-a:

@Override
    public Object instantiateItem(ViewGroup collection, int position) {
       int pageId = Integer.valueOf(mPagesId.get(position));
       View newView = createNewView();
       newView.setId(pageId);
       ((ViewPager) collection).addView(newView);
       // start post loading if there is active network connection
       if (ConnectionUtils.isOnline(mContext)) {
           TaskLoadPost loadPostTask = new TaskLoadPost();
           loadPostTask.execute(pageId);
       } else {
           DialogUtil.showNetworkErrorDialog((Activity) mContext);
       }
       return newView;
    }



В фоне заполняю вьюхи данными из Сети и там же получаю новый id, который добавляю в массив:

mPagesId.add(id);


После чего адаптер вновь вызывает метод instantiateItem(...), далее по позиции берется id из массива и все повторяется далее: добавили новое view, загрузили его, загрузили след. Id, поместили в массив и т.д.


На первых шагах все в порядке (рассматриваю только листание вправо сейчас), разве что по достижению 3 или 4 элемента адаптер перед инициализацией новой страницы вызывает метод удаления destroyItem():

((ViewPager) collection).removeView((View) view);

    View page = (View) view;
    mPagesId.remove(String.valueOf(page.getId()));
    notifyDataSetChanged();



ОК, удалили, все вроде бы в порядке. После этого размер массива становится равным 3м. Тут начинается самое интересное: после удаления 0 элемента мы в методе initiate вызываемся уже не как логично было бы предполагать со 2 элементом — position == 2 (ведь у нас хранится только 3 страницы), а с 3 — мы лезем по этой позиции за Id, но id там не находим, т.к. массив только что был «сжат». Ну да ладно, думаю, как-нибудь можно выкрутиться. Проскочили, листнули, вновь удалили, снова попадаем в в initiate… опять же логично ожидать position == 2, 3 ну или черт с ним, 4… но position приходит равным 1! Что это за единица и откуда и почему она берется — для меня большая загадка. Опять же говнокодом это можно обойти и в случае листания вправо далее вызывается только с позицией = 1 — почему и как мне не ясно.


В общем, суть вопроса: каким образом можно нормально синхронизировать и «подружить» какую-то свою структуру, храняющуюю вспомогательные данные для страниц во ViewPager, с тем поведением, что происходит у ViewPager-a и вызываемыми им методами добавления\удаления с непонятными позициями. Мне действительно нужен дополнительный массив синхронизированный с внутренним хранилищем View во ViewPager, иначе не представляется возможным загружать следующие\предыдущие страницы с API с правильными id-шниками, при этом удаляя ненужные страницы и id. Кто-нибудь сталкивался с чем-то подобным? Может, есть какие-то более элегантные задачи решить мою задачу? Может, я как-то не верно понимаю всю хитрость того, когда и как ViewPager вызывает методы своего адаптера? Для меня эти позиции действительно неясны, а без возможности их предсказания я не могу получать нужные id для загрузки следующих страниц и очистки старых.


Был бы очень благодарен за любой совет, бьюсь над этим уже порядка недели…
  • Вопрос задан
  • 7225 просмотров
Подписаться 10 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 1
Radegast
@Radegast
А зачем вы удаляете из своего списка? Пэйжер это делает только из-за соображений эффективности, насколько я знаю. Почему бы не оставить ваш список в покое? Если, например, пользователь стал листать назад, начнется опять загрузка того что уже было или чего-то другого?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы