PagerAdapter.notifyDataSetChanged не обновляет фрагменты
Мой Activity
содержит ViewPager
и пользовательский Adapter
, который расширяет FragmentStatePagerAdapter
. ViewPager
содержит 3 фрагмента
Код для удаления фрагментов из ViewPager
MainActivity
public void deleteElement(){
final int currentItem = mViewPager.getCurrentItem();
mPagerAdapter.removeItem(currentItem);
mPagerAdapter.notifyDataSetChanged();
}
CustomPagerAdapter
private ArrayList<Item> data;
public void removeItem(int index){
data.remove(index);
}
при удалении середины Fragment
(индекс 1):
- из
data
я удаляю правильный item
.
- Проблема в том, что я (я думаю)
Fragment
3 удаляется после notifyDataSetChanged
, а текущий Fragment
по-прежнему является фрагментом, который видел пользователь, и загружаемые данные из пакета SavedInstance
Таким образом, конечный результат заключается в том, что пользователь все еще видит тот же самый Fragment
, который он пытался удалить, что для него отстой.
Идеи?
***** РЕДАКТИРОВАТЬ ******
Похоже, ViewPager2 Возможности могут решить эту проблему, а также многие другие проблемы
Ответы
Ответ 1
Я знаю, что этот вопрос немного устарел, но было бы интересно узнать, что Google недавно решил эту проблему с помощью ViewPager2. Смотрите примеры здесь
Прежде всего, существует следующая зависимость в вашем файле build.gradle:
dependencies {
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta02'
}
Теперь вы можете заменить ваш ViewPager в своем XML файле на:
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
Затем вам нужно будет заменить ViewPager на ViewPager2 в своей деятельности
ViewPager2 требуется либо RecycleView.Adapter, либо FragmentStateAdapter:
public class TabAdapter extends FragmentStateAdapter {
private final List<Tab> tabs;
public TabAdapter(@NonNull FragmentManager fm, List<Tab> tabs, Lifecycle lifecycle) {
super(fm, lifecycle);
this.tabs = tabs;
}
@NonNull
@Override
public Fragment createFragment(int position) {
//create your fragment here
}
@Override
public int getItemCount() {
return tabs.size();
}
@Override
public long getItemId(int position) {
// use a distinct id for each item to allow the adapter to see the changes
}
}
Если вы использовали TabLayout, вы можете использовать TabLayoutMediator:
TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(tabLayout, viewPager, true, new TabLayoutMediator.OnConfigureTabCallback() {
@Override
public void onConfigureTab(@NotNull TabLayout.Tab tab, int position) {
// configure your tab here
tab.setText(tabs.get(position).getTitle());
}
});
tabLayoutMediator.attach();
Чтобы удалить данные, после удаления элемента из вашей коллекции вы можете вызвать метод notifyDataSetChanged()
или, более конкретно, notifyItemRemoved()
с позицией удаленного элемента.
Ответ 2
Попробуйте добавить это:
private class MyPagerAdapter extends FragmentStatePagerAdapter {
//... your existing code
@Override
public int getItemPosition(Object object){
return PagerAdapter.POSITION_NONE;
}
}
Ответ 3
У вас нет выбора, кроме как реализовать PagerAdapter#getItemPosition
. Рассматривая источник, как именно ViewPager определяет, как обновить свою позицию, добавить новые фрагменты или отбросить мертвые после notifyDataSetChanged
. Это не должно быть слишком сложно, вам просто нужно получить доступ к состоянию переданного фрагмента, и вам также нужно получить доступ к главному состоянию в вашей деятельности, которая поддерживает ваше упорядочение.
Также потребовалось реализовать getItemId
, чтобы вернуть согласованный идентификатор для каждого фрагмента, потому что они могут быть переупорядочены.
Вот как я обработал его в ViewPager фотографий.
private inner class PhotoPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
override fun getItem(position: Int): PhotoViewFragment {
// getItem is called to instantiate the fragment for the given page.
return PhotoViewFragment.newInstance(position, [email protected][position])
}
override fun getItemId(position: Int): Long {
return [email protected][position].ID!!.hashCode().toLong()
}
override fun getItemPosition(`object`: Any): Int {
val frag = `object` as PhotoViewFragment
val idx = [email protected] { ph -> ph.ID == frag.dataBinding.photo.ID }
return if (idx >= 0) idx else PagerAdapter.POSITION_NONE
}
override fun getCount(): Int {
return [email protected]
}
}
Ответ 4
Вы можете попробовать использовать FragmentPagerAdapter вместо FragmentStatePagerAdapter. Дело в том, что я тоже столкнулся с этой проблемой, и она мне помогла.
Ответ 5
Вы должны сначала установить адаптер на ноль, а затем установить его обратно:
int currentPosition = mViewPager.getCurrentItem();
mPagerAdapter.notifyDataSetChanged();
mViewPager.setAdapter(null);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setCurrentItem(currentPosition);
Ответ 6
Вы можете попробовать использовать FragmentStatePagerAdapter вместо публичного FragmentPagerAdapter
Его работа для меня..!