Обновлять ViewPager динамически?

Я не могу обновить содержимое в ViewPager.

Как правильно использовать методы instantiateItem() и getItem() в классе FragmentPagerAdapter?

Я использовал только getItem() для создания экземпляров и возврата моих фрагментов:

@Override
public Fragment getItem(int position) {
    return new MyFragment(context, paramters);
}

Это сработало хорошо. За исключением того, что я не могу изменить содержание.

Итак, я нашел это: ViewPager PagerAdapter не обновляет представление

"Мой подход заключается в использовании метода setTag() для любого экземпляра представления в методе instantiateItem()"

Теперь я хочу реализовать instantiateItem() для этого. Но я не знаю, что я должен вернуть (тип Object) и какова связь с getItem (int position)?

Я прочитал ссылку:

  • публичный абстрактный фрагмент getItem (int position)

    Вернуть фрагмент, связанный с указанной позицией.

  • открытый объект instantiateItem (контейнер ViewGroup, позиция int)

    Создайте страницу для данной позиции. Адаптер отвечает за добавление представления к указанному здесь контейнеру, хотя он должен только гарантировать, что это будет сделано к тому времени, когда он вернется из finishUpdate (ViewGroup). параметры

    контейнер Содержащий вид, в котором будет отображаться страница. position Позиция страницы, которую нужно создать.

    Возвращает

    Возвращает объект, представляющий новую страницу. Это не обязательно должен быть View, но может быть какой-то другой контейнер страницы.

но я все еще не понимаю

Вот мой код. Я использую пакет поддержки v4.

ViewPagerTest

public class ViewPagerTest extends FragmentActivity {
    private ViewPager pager;
    private MyFragmentAdapter adapter; 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pager1);

        pager = (ViewPager)findViewById(R.id.slider);

        String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};

        adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        pager.setAdapter(adapter);

        ((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                reload();
            }
        });
    }

    private void reload() {
        String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
        //adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        adapter.setData(data);
        adapter.notifyDataSetChanged();
        pager.invalidate();

        //pager.setCurrentItem(0);
    }
}

MyFragmentAdapter

class MyFragmentAdapter extends FragmentPagerAdapter {
    private int slideCount;
    private Context context;
    private String[] data;

    public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
        super(fm);
        this.slideCount = slideCount;
        this.context = context;
        this.data = data;
    }

    @Override
    public Fragment getItem(int position) {
        return new MyFragment(data[position], context);
    }

    @Override
    public int getCount() {
        return slideCount;
    }

    public void setData(String[] data) {
        this.data = data;
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
}

MyFragment

public final class MyFragment extends Fragment {
    private String text;

    public MyFragment(String text, Context context) {
        this.text = text;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.slide, null);
        ((TextView)view.findViewById(R.id.text)).setText(text);

        return view;
    }
}

Вот также кто-то с подобной проблемой, без ответов http://www.mail-archive.com/[email protected]/msg200477.html

Ответ 1

При использовании FragmentPagerAdapter или FragmentStatePagerAdapter лучше всего использовать только getItem() и не касаться instantiateItem() вообще. Интерфейс instantiateItem() - destroyItem() - isViewFromObject() на PagerAdapter - это интерфейс более низкого уровня, который FragmentPagerAdapter использует для реализации гораздо более простого интерфейса getItem().

Прежде чем вникать в это, я должен уточнить, что

, если вы хотите отключить фактические фрагменты, которые отображаются, вам нужно избегать FragmentPagerAdapter и использовать FragmentStatePagerAdapter.

В более ранней версии этого ответа была допущена ошибка использования FragmentPagerAdapter для его примера - это не сработает, потому что FragmentPagerAdapter никогда не уничтожает фрагмент после его отображения в первый раз.

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

Правильное решение - переопределить getItemPosition(). Когда вызывается notifyDataSetChanged(), ViewPager вызывает getItemPosition() на всех элементах своего адаптера, чтобы увидеть, нужно ли их перемещать в другую позицию или удалять.

По умолчанию getItemPosition() возвращает POSITION_UNCHANGED, что означает: "Этот объект в порядке, он не уничтожает и не удаляет его". Возвращение POSITION_NONE устраняет проблему, вместо этого говоря: "Этот объект больше не является элементом, который я показываю, удалите его". Таким образом, он имеет эффект удаления и воссоздания каждого отдельного элемента в вашем адаптере.

Это совершенно законное решение! Это исправление делает notifyDataSetChanged вести себя как обычный адаптер без использования утилиты просмотра. Если вы реализуете это исправление и производительность удовлетворительная, вы уходите на гонки. Выполнение задания.

Если вам нужна более высокая производительность, вы можете использовать реализацию fancier getItemPosition(). Здесь приведен пример создания пейджера фрагментов из списка строк:

ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();

FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
    public int getCount() {
        return titles.size();
    }

    public Fragment getItem(int position) {
        MyFragment fragment = new MyFragment();
        fragment.setTitle(titles.get(position));
        return fragment;
    }

    public int getItemPosition(Object item) {
        MyFragment fragment = (MyFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        if (position >= 0) {
            return position;
        } else {
            return POSITION_NONE;
        }
    }
});

В этой реализации будут отображаться только фрагменты, отображающие новые заголовки. Любые фрагменты, отображающие названия, которые все еще находятся в списке, вместо этого будут перемещены в их новую позицию в списке, а фрагменты с названиями, которые больше не находятся в списке, будут уничтожены.

Что делать, если фрагмент не был воссоздан, но нуждается в обновлении? Обновления живого фрагмента лучше всего обрабатывать самим фрагментом. Что преимущество наличия фрагмента, в конце концов - это его собственный контроллер. Фрагмент может добавить слушателя или наблюдателя к другому объекту в onCreate(), а затем удалить его в onDestroy(), тем самым управляя самими обновлениями. Вам не нужно вставлять весь код обновления внутри getItem(), как это делается в адаптере для ListView или других типов AdapterView.

Последнее - просто потому, что FragmentPagerAdapter не уничтожает фрагмент, не означает, что getItemPosition совершенно бесполезен в FragmentPagerAdapter. Вы можете использовать этот обратный вызов для изменения порядка ваших фрагментов в ViewPager. Однако он никогда не удалит их полностью из FragmentManager.

Ответ 2

Вместо того, чтобы возвращать POSITION_NONE из getItemPosition() и вызывать полный просмотр, сделайте следующее:

//call this method to update fragments in ViewPager dynamically
public void update(UpdateData xyzData) {
    this.updateData = xyzData;
    notifyDataSetChanged();
}

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(updateData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}

В ваших фрагментах должен реализоваться интерфейс UpdateableFragment:

public class SomeFragment extends Fragment implements
    UpdateableFragment{

    @Override
    public void update(UpdateData xyzData) {
         // this method will be called for every fragment in viewpager
         // so check if update is for this fragment
         if(forMe(xyzData)) {
           // do whatever you want to update your UI
         }
    }
}

и интерфейс:

public interface UpdateableFragment {
   public void update(UpdateData xyzData);
}

Ваш класс данных:

public class UpdateData {
    //whatever you want here
}

Ответ 3

для тех, кто по-прежнему сталкивается с той же проблемой, с которой сталкивался раньше, когда у меня есть ViewPager с 7 фрагментами. по умолчанию эти фрагменты загружают английский контент из службы api, но проблема здесь в том, что я хочу изменить язык из настроек и после завершения я хочу, чтобы ViewPager в основном действии обновлял фрагменты в соответствии с выбором языка от пользователя и загружал арабский контент, если пользователь выбрал арабский язык здесь, что я сделал, чтобы работать с первого раза

1- Вы должны использовать FragmentStatePagerAdapter, как указано выше.

2-on mainActivity я переопределяет onResume и сделал следующее

 if (!(mPagerAdapter == null)) {
mPagerAdapter.notifyDataSetChanged();
}

3-i переопределил getItemPosition() в mPagerAdapter и запустил POSITION_NONE.

 @Override
   public int getItemPosition(Object object) {
     return POSITION_NONE;
    }

работает как шарм

Ответ 4

Я столкнулся с этой проблемой и, наконец, решил ее сегодня, поэтому я записываю то, что узнал, и надеюсь, что это будет полезно для тех, кто новичок в Android ViewPager и обновляет, как и я. Я использую FragmentStatePagerAdapter в API-интерфейсе 17 и в настоящее время имеет всего 2 фрагмента. Я думаю, что должно быть что-то не правильно, пожалуйста, поправьте меня, спасибо. enter image description here

  • Сериализованные данные должны быть загружены в память. Это можно сделать, используя CursorLoader/AsyncTask/Thread. Будет ли он автоматически загружен, зависит от вашего кода. Если вы используете CursorLoader, он автоматически загружается, так как есть зарегистрированный наблюдатель данных.

  • После вызова viewpager.setAdapter(pageradapter) адаптер getCount() постоянно вызывается для создания фрагментов. Поэтому, если данные загружаются, getCount() может возвращать 0, поэтому вам не нужно создавать фиктивные фрагменты без отображения данных.

  • После загрузки данных адаптер не будет создавать фрагменты автоматически, так как getCount() все равно 0, поэтому мы можем установить фактически загруженный номер данных, который будет возвращен getCount(), затем вызвать адаптер notifyDataSetChanged(). ViewPager начинают создавать фрагменты (только первые 2 фрагмента) по данным в памяти. Это делается до возврата notifyDataSetChanged(). Затем ViewPager имеет нужные фрагменты.

  • Если данные в базе данных и в памяти обновляются (записываются) или обновляются данные в памяти (записываются обратно) или обновляются только данные в базе данных. В последних двух случаях, если данные не загружаются автоматически из базы данных в память (как упоминалось выше). Адаптер ViewPager и пейджер просто обрабатывают данные в памяти.

  • Поэтому, когда данные в памяти обновляются, нам просто нужно вызвать адаптер notifyDataSetChanged(). Поскольку фрагмент уже создан, адаптер onItemPosition() будет вызываться до возвращения notifyDataSetChanged(). Ничего не нужно делать в getItemPosition(). Затем данные обновляются.

Ответ 5

Попробуйте destroyDrawingCache() на ViewPager после notifyDataSetChanged() в вашем коде.

Ответ 6

После нескольких разочарований, пытаясь решить все вышеперечисленные решения, чтобы решить эту проблему, а также попробовать множество решений по другим подобным вопросам, например , this и , которые все НЕ УДАЛИТЬ, чтобы решить эту проблему и сделать ViewPager для уничтожения старого Fragment и заполнить pager с новым Fragment s. Я решил проблему следующим образом:

1) Сделайте класс ViewPager для расширения FragmentPagerAdapter следующим образом:

 public class myPagerAdapter extends FragmentPagerAdapter {

2) Создайте элемент для ViewPager, который хранит title и Fragment следующим образом:

public class PagerItem {
private String mTitle;
private Fragment mFragment;


public PagerItem(String mTitle, Fragment mFragment) {
    this.mTitle = mTitle;
    this.mFragment = mFragment;
}
public String getTitle() {
    return mTitle;
}
public Fragment getFragment() {
    return mFragment;
}
public void setTitle(String mTitle) {
    this.mTitle = mTitle;
}

public void setFragment(Fragment mFragment) {
    this.mFragment = mFragment;
}

}

3) Создайте конструктор ViewPager для моего экземпляра FragmentManager, чтобы сохранить его в моем class следующим образом:

private FragmentManager mFragmentManager;
private ArrayList<PagerItem> mPagerItems;

public MyPagerAdapter(FragmentManager fragmentManager, ArrayList<PagerItem> pagerItems) {
    super(fragmentManager);
    mFragmentManager = fragmentManager;
    mPagerItems = pagerItems;
}

4) Создайте метод для повторного набора данных adapter с новыми данными, исключив все предыдущие Fragment из самого FragmentManager, чтобы сделать adapter снова установите новый Fragment из нового списка следующим образом:

public void setPagerItems(ArrayList<PagerItem> pagerItems) {
    if (mPagerItems != null)
        for (int i = 0; i < mPagerItems.size(); i++) {
            mFragmentManager.beginTransaction().remove(mPagerItems.get(i).getFragment()).commit();
        }
    mPagerItems = pagerItems;
}

5) Из контейнера Activity или Fragment не переустанавливайте адаптер с новыми данными. Установите новые данные с помощью метода setPagerItems с новыми данными следующим образом:

ArrayList<PagerItem> pagerItems = new ArrayList<PagerItem>();
    pagerItems.add(new PagerItem("Fragment1", new MyFragment1()));
    pagerItems.add(new PagerItem("Fragment2", new MyFragment2()));

    mPagerAdapter.setPagerItems(pagerItems);
    mPagerAdapter.notifyDataSetChanged();

Надеюсь, это поможет.

Ответ 7

По какой-то причине ни один из ответов не работал у меня, поэтому мне пришлось переопределить метод restoreState, не вызвав super в моем фрагментеStatePagerAdapter. Код:

private class MyAdapter extends FragmentStatePagerAdapter {

    // [Rest of implementation]

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {}

}

Ответ 8

Я немного изменил решение, предоставленное Биллом Филлипсом, чтобы удовлетворить мои потребности

private class PagerAdapter extends FragmentStatePagerAdapter{
    Bundle oBundle;
    FragmentManager oFragmentManager;
    ArrayList<Fragment> oPooledFragments;

public PagerAdapter(FragmentManager fm) {
    super(fm);
    oFragmentManager=fm;

    }
@Override
public int getItemPosition(Object object) {

    Fragment oFragment=(Fragment)object;
    oPooledFragments=new ArrayList<>(oFragmentManager.getFragments());
    if(oPooledFragments.contains(oFragment))
        return POSITION_NONE;
    else
        return POSITION_UNCHANGED;
    } 
}

так что getItemPosition() возвращает POSITION_NONE только для тех фрагментов, которые в настоящее время находятся в FragmentManager, когда вызывается getItemPosition. (Обратите внимание, что связанные с ним FragmentStatePager и ViewPager содержатся в фрагменте не в Activity)

Ответ 9

У меня была аналогичная проблема, но я не хочу доверять существующим решениям (имена закодированных тегов и т.д.), и я не мог заставить M-WaJeEh работать для меня. Вот мое решение:

Я сохраняю ссылки на фрагменты, созданные в getItem в массиве. Это прекрасно работает, пока активность не уничтожается из-за конфигурации или отсутствия памяти или что-то еще (- > при возврате к активности фрагменты возвращаются в свое последнее состояние без вызова getItem и, таким образом, без обновления массива).

Чтобы избежать этой проблемы, я применил instantiateItem (ViewGroup, int) и обновил свой массив, например:

        @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Object o = super.instantiateItem(container, position);
        if(o instanceof FragmentX){
            myFragments[0] = (FragmentX)o;
        }else if(o instanceof FragmentY){
            myFragments[1] = (FragmentY)o;
        }else if(o instanceof FragmentZ){
            myFragments[2] = (FragmentZ)o;
        }
        return o;
    }

Итак, с одной стороны, я рад, что нашел решение, которое работает для меня, и хотел поделиться им с вами, но я также хотел спросить, кто-то еще пытался что-то подобное, и есть ли причина, по которой я не должен делать это так? Пока это работает очень хорошо для меня...

Ответ 10

Я использую EventBus для обновления содержимого Fragment в ViewPager. Логика проста, так же как документ EventBus, как это сделать. Нет необходимости управлять экземпляром FragmentPagerAdapter. Код здесь:

1: Определить события

Определите, какое сообщение необходимо обновить.

public class UpdateCountEvent {
    public final int count;

    public UpdateCountEvent(int count) {
        this.count = count;
    }
}

2.Подробнее о подписчиках

Напишите ниже код в Фрагменте, который необходим для обновления.

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);  
    super.onStop();
}

public void onEvent(UpdateCountEvent event) {//get update message
    Toast.makeText(getActivity(), event.count, Toast.LENGTH_SHORT).show();
}

События 3.Post

Введите ниже код в другой Activity или другой Fragment, который должен обновить параметр

//input update message
EventBus.getDefault().post(new UpdateCountEvent(count));

Ответ 11

Если вы хотите использовать FragmentStatePagerAdapter, просмотрите https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=37990. Есть проблемы с FragmentStatePagerAdapter, которые могут или могут не беспокоить ваш случай использования.

Кроме того, у ссылки есть несколько решений тоже. Возможно, это соответствует вашим требованиям.

Ответ 12

У меня была такая же проблема, и я искал слишком много раз. Любой ответ, полученный в stackoverflow или через google, не был решением моей проблемы. Моя проблема была легкой. У меня есть список, я показываю этот список с помощью viewpager. Когда я добавляю новый элемент в начало списка, и я обновляю nopings плеера viewpager. Мое окончательное решение было очень простым, и каждый может использовать его. Когда новый элемент добавлен в список и вы хотите обновить список. Сначала установите адаптер viewpager в значение null, затем заново создайте адаптер и установите я на него в viewpager.

myVPager.setAdapter(null);
myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(),newList);
myVPager.setAdapter(myFragmentAdapter);

Убедитесь, что ваш адаптер должен расширять FragmentStatePagerAdapter

Ответ 13

Я пробовал так много разных подходов, ни одна из них не очень беспокоила мою проблему. Ниже я расскажу, как я решаю это с помощью набора решений, предоставленных вами всеми. Спасибо всем.

class PagerAdapter extends FragmentPagerAdapter {

    public boolean flag_refresh=false;

    public PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int page) {
        FragmentsMain f;
        f=new FragmentsMain();
        f.page=page;
        return f;
    }

    @Override
    public int getCount() {
        return 4;
    }

    @Override
    public int getItemPosition(Object item) {
        int page= ((FragmentsMain)item).page;

        if (page == 0 && flag_refresh) {
            flag_refresh=false;
            return POSITION_NONE;
        } else {
            return super.getItemPosition(item);
        }
    }

    @Override
    public void destroyItem(View container, int position, Object object) {

        ((ViewPager) container).removeView((View) object);
    }
}

Я хочу только обновить страницу 0 после onResume().

 adapter=new PagerAdapter(getSupportFragmentManager());
 pager.setAdapter(adapter);

@Override
protected void onResume() {
    super.onResume();

    if (adapter!=null) {
        adapter.flag_refresh=true;
        adapter.notifyDataSetChanged();
    }
}

В моем FragmentsMain есть общедоступная целая страница, которая может рассказать мне, является ли она страницей, которую я хочу обновить.

public class FragmentsMain extends Fragment {

private Cursor cursor;
private static Context context;
public int page=-1;

Ответ 14

Я знаю, что опаздываю на вечеринку. Я исправил проблему, вызвав TabLayout#setupWithViewPager(myViewPager); сразу после FragmentPagerAdapter#notifyDataSetChanged();

Ответ 15

Это решение не будет работать для всех, но в моем случае каждый фрагмент в моем ViewPager - это другой класс, и только один из них когда-либо существовал одновременно.

С этим ограничением это решение безопасно и должно быть безопасным для использования в производстве.

private void updateFragment(Item item) {

    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    for (Fragment fragment : fragments) {

        if (fragment instanceof MyItemFragment && fragment.isVisible()) {
            ((MyItemFragment) fragment).update(item);
        }

    }
}

Если у вас несколько версий одного и того же фрагмента, вы можете использовать эту же стратегию для вызова методов на этих фрагментах, чтобы определить, является ли это фрагментом, который вы хотите обновить.

Ответ 16

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

  • Скопируйте источник для FragmentStatePagerAdapter (похоже, он не обновлялся в возрасте).

  • Переопределить notifyDataSetChanged()

    @Override
    public void notifyDataSetChanged() {
        mFragments.clear();
        super.notifyDataSetChanged();
    }
    
  • Добавьте проверку работоспособности destroyItem() для предотвращения сбоев:

    if (position < mFragments.size()) {
        mFragments.set(position, null);
    }
    

Ответ 17

Принятый ответ не понимает, поэтому добавлено простое решение. найти Рабочее решение.

Просто сообщите об этом адаптеру, он работает потрясающе,

Код ссылки

 void setAdapter(int position) {
        PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(pagerAdapter);
        // when notify then set manually current position.
        viewPager.setCurrentItem(position);
        pagerAdapter.notifyDataSetChanged();
    }

вызывают этот код при настройке адаптера и когда вы хотите обновить интерфейс.

В своем фрагменте добавьте этот код для обновления Используйте instanceof для контекста трансляции.

((YourActivityName) getContext()).setAdapter(selectedTabPosition);

Этот общий код помогает только тем, кто находит рабочее решение, надеюсь, что он полезен!

Ответ 18

Я рассмотрел все вышеперечисленные ответы и ряд других сообщений, но все еще не мог найти что-то, что сработало для меня (с разными типами фрагментов, а также с динамическим добавлением и удалением вкладок). Следующим подходом FWIW является то, что сработало для меня (в случае, если у кого-то есть такие же проблемы).

public class MyFragmentStatePageAdapter extends FragmentStatePagerAdapter {
    private static final String TAB1_TITLE = "Tab 1";
    private static final String TAB2_TITLE = "Tab 2";
    private static final String TAB3_TITLE = "Tab 3";

    private ArrayList<String> titles = new ArrayList<>();
    private Map<Fragment, Integer> fragmentPositions = new HashMap<>();


    public MyFragmentStatePageAdapter(FragmentManager fm) {
        super(fm);
    }


    public void update(boolean showTab1, boolean showTab2, boolean showTab3) {
        titles.clear();

        if (showTab1) {
            titles.add(TAB1_TITLE);
        }
        if (showTab2) {
            titles.add(TAB2_TITLE);
        }
        if (showTab3) {
            titles.add(TAB3_TITLE);
        }
        notifyDataSetChanged();
    }


    @Override
    public int getCount() {
        return titles.size();
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = null;

        String tabName = titles.get(position);
        if (tabName.equals(TAB1_TITLE)) { 
            fragment =  Tab1Fragment.newInstance();
        } else if (tabName.equals(TAB2_TITLE)) {
            fragment =  Tab2Fragment.newInstance();
        } else if (tabName.equals(TAB3_TITLE)) {
            fragment =  Tab3Fragmen.newInstance();
        } 

        ((BaseFragment)fragment).setTitle(tabName);
        fragmentPositions.put(fragment, position);
        return fragment;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles.get(position);
    }

    @Override
    public int getItemPosition(Object item) {
        BaseFragment fragment = (BaseFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        Integer fragmentPosition = fragmentPositions.get(item);
        if (fragmentPosition != null && position == fragmentPosition) {
            return POSITION_UNCHANGED;
        } else {
            return POSITION_NONE;
        }
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
        fragmentPositions.remove(object);
    }
}

Ответ 19

Используйте FragmentStatePagerAdapter вместо FragmentPagerAdapter, если вы хотите воссоздать или перезагрузить фрагмент на основе индекса. Например, если вы хотите перезагрузить фрагмент, отличный от FirstFragment, вы можете проверить экземпляр и вернуть позицию следующим образом

 public int getItemPosition(Object item) {
    if(item instanceof FirstFragment){
       return 0;
    }
    return POSITION_NONE;
 }

Ответ 20

Вот моя реализация, которая включает в себя информацию от @Bill Phillips One большую часть времени получает фрагментированное кэширование, за исключением случаев, когда данные изменились. Просто, и, кажется, работает нормально.

MyFragmentStatePagerAdapter.java

private boolean mIsUpdating = false;
public void setIsUpdating(boolean mIsUpdating) {
        this.mIsUpdating = mIsUpdating;
    }


@Override
public int getItemPosition(@NonNull Object object) {

    if (mIsUpdating) {
        return POSITION_NONE;
    }
    else {
        return super.getItemPosition(object);
    }
}

MyActivity.java

mAdapter.setIsUpdating(true);
mAdapter.notifyDataSetChanged();
mAdapter.setIsUpdating(false);