26

我使用ViewPager示例,其中ActionBar標籤取自Android文檔hereIllegalStateException:應用程序的PagerAdapter在不調用PagerAdapter的情況下更改了適配器的內容#notifyDataSetChanged

不幸的是,當我叫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方法以對notifyDataSetChanged的調用結束。正如文檔建議的那樣:

PagerAdapter支持數據集更改。數據集更改必須在 主線程上發生,並且必須以對來自BaseAdapter的AdapterView適配器的調用notifyDataSetChanged() 結束。

回答

18

我很難讓我的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); 
    } 

注意最後三個操作的順序。在原始示例中,notifyDataSetChanged是在mActionBar.addTab函數之後調用的。

不幸的是,只要您撥打ActionBar上的addTab,就會自動選擇您添加的第一個選項卡。因此,onTabSelected事件被觸發,並在嘗試檢索該頁面時,它會顯示IllegalStateException,因爲它會注意到預期項目數和實際項之間的差異。

+0

我一直在尋找這一段時間。我是唯一一個發現奇怪的錯誤,就像我沒有調用notifyDataSetChanged()一樣,當我真的需要執行操作時(setCurrentItem在我的情況)notifyDataSetChanged()之後? – wizurd

8

我通過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); 

} 
+0

好東西就在這裏......謝謝! – worked

0

FragmentStatePager適配器有同樣的問題。在onResume()當reInitialize adpater和ViewPager時,將顯示相同的錯誤IllegalStateException。解決方案:

添加選項卡addtab時,請通過將setSelected params設置爲false來選擇未選中的選項卡。

actionBar.addTab(tab,false); 

我覺得異常出現,因爲覆蓋像下面

viewPager.setCurrentItem(tab.getPosition()); 

onTabSelected()方法因此調用addTab()當它不承認這viewPager和適配器添加標籤來的。

3

我得到這個錯誤,如您通過內getCount將()引用標籤:

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

當實例化,這應該既可以通過在一個單獨的變量,或尋呼機應後成立該集合已被填充/變異。

0

我的問題並不完全相同,但情況相似。

我有一個AlertDialog顯示在具有ViewPager和使用AppCompatActivity的佈局中。旋轉屏幕時,我得到IllegalStateException並崩潰。

感謝來自answer @almisoft和@Zagorax的答案,我在顯示對話框之前嘗試調用notifyDataSetChanged();,並且問題似乎消失了。

1

試試這個。我曾

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(); 

     } 
0

一線答案只需添加viewpageadapter.notifyDataSetChanded()

相關問題