0

My MainActivity содержит viewPager.Заменить фрагмент в Viewpager (notifyDataSetChanged не работает)

В MainActivity.java, я установил адаптер для viewpager. Адаптер расширяет FragmentStatePagerAdapter. Фрагмент, который я хочу заменить, - это cameraFragment. Поэтому, когда пользователь нажимает кнопку переключателя камеры, я хочу показать фрагмент камеры, на этот раз с фронтальной камерой.

При нажатии кнопки «Камера» я удаляю фрагмент из массива фрагментов, которые я передал пользовательскому адаптеру. Я добавляю новый фрагмент и вызываю notifydatasetchanged. Однако это не приводит к добавлению нового фрагмента. Как добиться динамической замены фрагментов в представлении, который поддерживает мой пользовательский адаптер пейджера состояния? Код:

mainPageFragments = new ArrayList<>(); 
mainPageFragments.add(new ResultsFragment_()); 
mainPageFragments.add(DemoCameraFragment_.newInstance(false)); 
pagerAdapter = new MainViewPagerAdapter(getSupportFragmentManager(),mainPageFragments); 

Для замены фрагмента: Получив соответствующее событие, что я делаю,

mainPageFragments.remove(1); 
    if (event.getCameraState().equals(CameraSwitchButton.CameraTypeEnum.BACK)) { 
     mainPageFragments.add(DemoCameraFragment.newInstance(false)); 
    } else { 
     mainPageFragments.add(DemoCameraFragment.newInstance(true)); 

    } 
    // Not Working... 
    pagerAdapter.notifyDataSetChanged(); 

Adapter Код:

public class MainViewPagerAdapter extends FragmentStatePagerAdapter { 

ArrayList<Fragment> fragmentsArray; 

public MainViewPagerAdapter(FragmentManager fm, ArrayList<Fragment> fragmentsArray) { 
    super(fm); 
    this.fragmentsArray = fragmentsArray; 
} 

@Override 
public Fragment getItem(int position) { 
    return fragmentsArray.get(position); 
} 

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

@Override 
public int getItemPosition(Object object) { 
    return super.getItemPosition(object); 
} 
} 
+0

post какой-либо код что вы сделали – Mano

+0

@Mano. Любые мысли о том, как обновлять/заменять фрагмент? Ясно, что я что-то пропускаю. Я не хочу перезагружать адаптер. Похоже, что это дорогостоящая операция (если количество страниц/фрагментов увеличивается. Также мне нужно только заменить один фрагмент, поэтому повторная копирование всех остальных не имеет никакого смысла. – Rohan

+0

Сообщение о приятности также для кода MainViewPagerAdapter. – Okas

ответ

2

Ваш MainViewPagerAdapter.getItemPosition является причиной вашей проблемы ,

Реализация по умолчанию всегда возвращает POSITION_UNCHANGED. Чтобы пейджер удалял фрагмент, вы должны вернуть PagerAdapter.POSITION_NONE для удаляемых фрагментов.

Кроме того, ваш текущий дизайн противоречит идее FragmentStatePagerAdapter. Из FragmentStatePagerAdapter documentation: «Эта версия пейджера более полезна, когда имеется большое количество страниц, больше похоже на просмотр списка. Когда страницы не видны пользователю, весь их фрагмент может быть уничтожен, сохраняя сохраненный состояние этого фрагмента. Это позволяет пейджеру удерживать гораздо меньше памяти, связанную с каждой посещенной страницей, по сравнению с FragmentPagerAdapter за счет потенциально большего количества накладных расходов при переключении между страницами ».

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

+0

Даже если бы я должен был реализовать адаптер таким образом, как мне заменить фрагмент? Я уже прочитал стандартную реализацию getItemPosition. Причина, по которой я пошел с FragmentStatePageAdapter, заключается в том, что есть хороший шанс количество страниц в viewpager будет увеличиваться. Я все еще не могу понять, что я должен сделать в методе getItemPosition, чтобы исправить мою проблему. – Rohan

+1

Вы должны отдельно отслеживать, какие фрагменты (ы) вы хотите сохранить и какие из них удалить. Затем, когда что-то меняется, вы должны вызвать notifyDataSetChanged(). Затем пейджер вызовет ваш метод getItemPosition. Вы должны вернуть POSITION_NONE для тех, кого хотите удалить, а затем пейджер удалит их для вас. – Okas

+0

Спасибо @Okas. Я внес изменения в соответствии с вашими сообщениями и разместил ответ ниже. – Rohan

0

Благодаря @Okas. Я сделал следующее изменение для getItemPosition в моем подклассе FragmentStatePagerAdapter.

@Override 
public int getItemPosition(Object object) { 
    if (object instanceof DemoCameraFragment_) 
     return POSITION_NONE; 
    return super.getItemPosition(object); 
} 

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

Смежные вопросы