IllegalStateException: PagerAdapter приложения изменил содержимое адаптера, не вызывая PagerAdapter # notifyDataSetChanged

Я использую пример ViewPager с вкладками ActionBar взятыми из документации по Android здесь .

К сожалению, как только я addTab метод addTab , приложение вылетает со следующим исключением:

IllegalStateException: PagerAdapter приложения изменил содержимое адаптера, не вызывая PagerAdapter # notifyDataSetChanged! Ожидаемое количество элементов адаптера 0, найдено 1.

Это код FragmentPagerAdapter :

 public static class TabsAdapter extends FragmentPagerAdapter implements ActionBar.TabListener, ViewPager.OnPageChangeListener { private final Context mContext; private final ActionBar mActionBar; private final ViewPager mViewPager; private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); static final class TabInfo { private final Class<?> clss; private final Bundle args; TabInfo(Class<?> _class, Bundle _args) { clss = _class; args = _args; } } public TabsAdapter(Activity activity, ViewPager pager) { super(activity.getFragmentManager()); mContext = activity; mActionBar = activity.getActionBar(); mViewPager = pager; mViewPager.setAdapter(this); mViewPager.setOnPageChangeListener(this); } public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) { TabInfo info = new TabInfo(clss, args); tab.setTag(info); tab.setTabListener(this); mTabs.add(info); mActionBar.addTab(tab); notifyDataSetChanged(); } @Override public int getCount() { return mTabs.size(); } @Override public Fragment getItem(int position) { TabInfo info = mTabs.get(position); return Fragment.instantiate(mContext, info.clss.getName(), info.args); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { mActionBar.setSelectedNavigationItem(position); } @Override public void onPageScrollStateChanged(int state) { } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { Object tag = tab.getTag(); for (int i=0; i<mTabs.size(); i++) { if (mTabs.get(i) == tag) { mViewPager.setCurrentItem(i); } } } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { } } } 

Я не изменяю свой адаптер в любой другой части моего кода, и я addTab метод addTab из основного потока, метод addTab заканчивается вызовом notifyDataSetChanged . Как рекомендует документация:

PagerAdapter поддерживает изменения набора данных. Изменения в наборе данных должны происходить в основном потоке и должны заканчиваться вызовом notifyDataSetChanged (), аналогичным адаптерам адаптера, полученным из BaseAdapter.

Solutions Collecting From Web of "IllegalStateException: PagerAdapter приложения изменил содержимое адаптера, не вызывая PagerAdapter # notifyDataSetChanged"

Мне было трудно ViewPager работать ViewPager . В конце концов, кажется, что пример в документации неверен.

Метод addTab должен быть следующим:

 public void addTab(Tab tab, Class<?> clss, Bundle args) { TabInfo info = new TabInfo(clss, args); tab.setTag(info); tab.setTabListener(this); mTabs.add(info); notifyDataSetChanged(); mActionBar.addTab(tab); } 

Обратите внимание на порядок последних трех операций. В исходном примере после функции mActionBar.addTab .

К сожалению, как только вы вызываете addTab в ActionBar , автоматически выбирается первая добавленная вкладка. Из-за этого событие onTabSelected запускается, и, пытаясь извлечь страницу, это вызывает IllegalStateException потому что оно замечает несоответствие между ожидаемым количеством элементов и фактическим.

Я исправил его callinig notifyDataSetChanged () один раз и сразу перед следующим вызовом getCount ():

 private boolean doNotifyDataSetChangedOnce = false; @Override public int getCount() { if (doNotifyDataSetChangedOnce) { doNotifyDataSetChangedOnce = false; notifyDataSetChanged(); } return actionBar.getTabCount(); } private void addTab(String text) { doNotifyDataSetChangedOnce = true; Tab tab = actionBar.newTab(); tab.setText(text); tab.setTabListener(this); actionBar.addTab(tab); } private void removeTab(int position) { doNotifyDataSetChangedOnce = true; actionBar.removeTabAt(position); } 

Я получал эту ошибку, как вы, ссылаясь на вкладки в getCount ():

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

При создании экземпляра это должно быть передано как отдельная переменная, или пейджер должен быть настроен после того, как коллекция была заполнена / мутирована.

Моя проблема была не совсем то же самое, но подобным контекстом.

У меня есть AlertDialog, который отображается в макете с ViewPager и использует AppCompatActivity. При повороте экрана я получал исключение IllegalStateException и сбой.

Благодаря ответам от @almisoft и @Zagorax, я попытался позвонить notifyDataSetChanged(); Прямо перед тем, как я покажу диалог, и проблема, похоже, исчезла.

У меня была та же проблема в адаптере FragmentStatePager . onResume() При повторной инициализации adpater и IllegalStateException будет отображаться та же ошибка IllegalStateException . Решение:

При добавлении вкладки addtab выберите вкладку, которая не будет выбрана, установив для параметра setSelected значение false.

  actionBar.addTab(tab,false); 

Я думаю, что исключение появилось из-за переопределения onTabSelected() например, следующего

  viewPager.setCurrentItem(tab.getPosition()); 

Поэтому при вызове addTab() он не распознал, какой viewPager и адаптер должен добавить вкладку.

попробуй это. я работал

 protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); System.out.println("Asyncrona onPostExecute"); /*::::::::::::::::::: Guardo los cambios ::::::::::::::*/ //menuTabs = menuTabs2; viewPager = (ViewPager) rootView.findViewById(R.id.viewPager_menu); costumAdapter = new CostumAdapter2(getActivity().getSupportFragmentManager()); costumAdapter.notifyDataSetChanged(); viewPager.setAdapter(costumAdapter); tabLayout = (TabLayout) rootView.findViewById(R.id.tablayout_menu); tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { System.out.println(" La Seleccionado: " + tab.getText()+", POSICION: "+tab.getPosition()); viewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabUnselected(TabLayout.Tab tab) { viewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabReselected(TabLayout.Tab tab) { viewPager.setCurrentItem(tab.getPosition()); } }); viewPager.setAdapter(costumAdapter); tabLayout.setupWithViewPager(viewPager); loading.closeMessage(); } 

Ответ One Line просто добавляет viewpageadapter.notifyDataSetChanded ()