Вставить страницы в середине FragmentPageAdapter

Я использую ViewPager из ViewPageIndicator, и мне нужно иметь возможность динамически вставлять один фрагмент в средний других.

Я попытался управлять моделью с помощью FragmentPagerAdapter и FragmentStatePagerAdapter (как из кода поддержки v4), так и, похоже, никоим образом не удается вставить страницы посередине. И второй работает только в том случае, если я наивно выполняю getItemPosition, всегда возвращая POSITION_NONE, но это вызывает полное восстановление страниц каждый раз, когда я сажусь.

Проблема, которую я наблюдал с FragmentStatePagerAdapter (FSP), такова:

  • Я начинаю с двух страниц [A] [B]
  • Затем я вставляю [C] в середину [A] [C] [B]. После вставки я вызываю notifyDataSetchange()
  • Затем FSP вызывает getItemPosition для [A] и получает 0
  • Затем FSP вызывает geTItemPosition для [B] и получает 2. И он говорит... Ohhh Я должен уничтожить [B] и сделать mFragments.set(2, null), а затем, поскольку он имеет только два элемента в mFragments array он генерирует исключение IndexOutOfBoundsException

Если немного взглянуть на код, кажется, что если фрагментStatePagerAdapter не поддерживает вставку в середине. Это правильно или я чего-то не хватает?

Update: Вставка в адаптере выполнена логически, когда верно определенное кодирование, страницы увеличиваются на единицу. Создание фрагмента выполняется с помощью конструктора в getItem() следующим образом:

void setCondition(boolean condition) {
   this.condition=condition;
   notifyDataSetChanged();
}
public int getCount(){
    return condition?3:2;
}
public Fragment getItem(int position) {
    if(position==0) 
        return new A();
    else if(position==1)
        return condition?new C():new B();
    else if(position==2 && condition)
        return new B();
    else throw new RuntimeException("Not expected");
}
public int getItemPosition(Object object) {
    if(object instanceof A) return 0;
    else if(object instanceof B) return condition?2:1;
    else if(object instanceof C) return 1;
} 

Решение:

Как сказано в принятом ответе, ключ состоит в реализации getItemId().

Убедитесь, что вы используете хотя бы R9 (июнь 2012 г.) версию библиотеки поддержки Android. Потому что этот метод был добавлен в него. До этой версии этот метод не существует, и адаптер неправильно управляет вставками. Также убедитесь, что вы используете FragmentPageAdapter, потому что FragmentStatePagerAdapter все еще не работает, потому что он не использует идентификаторы.

Ответы

Ответ 1

Ты забыл об одном методе.
Переопределите getItemId (int position) из FragmentPagerAdapter, который просто возвращает позицию, чтобы вернуть что-то, что будет идентифицировать экземпляр фрагмента.

public long getItemId(int position) {
    switch (position) {
    case 0:
        return 0xA;
    case 1:
        return condition ? 0xC : 0xB;
    case 2:
        if (condition) {
            return 0xB;
        }
    default:
        throw new IllegalStateException("Position out of bounds");
    }
}