FragmentStateAdapter не вызывает createFragment при вызове notifyDataSetChanged

#android #android-viewpager2 #fragmentstateadapter

#Android #android-viewpager2 #fragmentstateadapter

Вопрос:

Я использую a ViewPager2 вместе с a FragmentStateAdapter .

 public class MyAdapter extends FragmentStateAdapter {

    public MyAdapter(@NonNull Fragment fragment) {
        super(fragment);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return MyFragment.newInstance(MyClass.func(position));
    }

    @Override
    public int getItemCount() {
        return MyClass.NUM;
    }

}
  

К сожалению, вызов notifyDataSetChanged() адаптера вообще не имеет никакого эффекта. (Вызов notifyItemChanged(position) работает нормально.)

Как я могу это решить?

Ответ №1:

Я создал отчет об ошибке для этого здесь, в IssueTracker. Для меня, однако, даже методы notifyItemChanged(position:) and notifyItemRangeChanged(positionStart:itemCount:) ведут себя некорректно.

Ошибка связана с реализацией FragmentStateAdapter.getItemId(position:) метода по умолчанию, который просто возвращает position переданное в него. Поэтому itemId для каждого position будет одинаковым до и после FragmentStateAdapter.notifyDataSetChanged() вызова, и поэтому ни один из Fragment них никогда не будет воссоздан.

Одним из возможных обходных путей является присвоение каждой странице уникального идентификатора в вашей FragmentStateAdapter реализации и присвоение нового идентификатора каждой странице при notifyDataSetChanged() каждом вызове метода. Смотрите init Блок в ViewPagerAdapter классе ниже, который облегчает этот обходной путь: AdapterDataObserver объект зарегистрирован в этом init блоке таким образом, что он получает обратный вызов при каждом notifyDataSetChanged() вызове.

 class ViewPagerAdapter(fragmentActivity: FragmentActivity) :
    FragmentStateAdapter(fragmentActivity) {

    private var counter = 0L
    private var itemIds: List<Long>

    init {
        itemIds = generateListOfItemIds()

        val adapterDataObserver = object : AdapterDataObserver() {

            override fun onChanged() {
                itemIds = generateListOfItemIds()
            }
        }

        registerAdapterDataObserver(adapterDataObserver)
    }

    override fun createFragment(position: Int): Fragment {
        return PageFragment.newInstance(position)
    }

    override fun getItemCount(): Int {
        return itemIds.size
    }

    override fun getItemId(position: Int): Long {
        return itemIds[position]
    }

    override fun containsItem(itemId: Long): Boolean {
        return itemIds.contains(itemId)
    }

    private fun generateListOfItemIds() = (1..5).map { counter   }
}
  

Комментарии:

1. Смотрите Здесь минимальное приложение для Android, которое демонстрирует этот ViewPagerAdapter класс.

Ответ №2:

Перед установкой adapter() на ваш viewpager. Сделать viewPager.setSaveFromParentEnabled(false);