26

Tôi đang sử dụng ví dụ ViewPager với ActionBar tab lấy từ tài liệu Android here.IllegalStateException: PagerAdapter của ứng dụng thay đổi nội dung của bộ chuyển đổi mà không gọi PagerAdapter # notifyDataSetChanged

Thật không may, ngay sau khi tôi gọi addTab phương pháp, các ứng dụng bị treo với ngoại lệ sau:

IllegalStateException: Các ứng dụng của PagerAdapter thay đổi nội dung các adapter mà không gọi PagerAdapter # notifyDataSetChanged! Dự kiến ​​mục bộ chuyển đổi số 0, tìm thấy 1.

Đây là mã 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) { 
     } 
    } 
} 

Tôi không thay đổi bộ chuyển đổi của tôi trong bất kỳ phần nào khác của mã của tôi và tôi đang gọi addTab phương pháp từ chủ đề chính, phương pháp addTab kết thúc bằng một cuộc gọi đến notifyDataSetChanged. Theo tài liệu đề xuất cần thực hiện:

PagerAdapter hỗ trợ thay đổi tập dữ liệu. Thay đổi bộ dữ liệu phải xuất hiện trên chủ đề chính và phải kết thúc bằng một cuộc gọi để thông báoDataSetChanged() tương tự như bộ điều hợp AdapterView có nguồn gốc từ BaseAdapter.

Trả lời

18

Tôi đã gặp khó khăn khi làm việc ViewPager hoạt động. Cuối cùng, có vẻ như ví dụ trong tài liệu là sai.

Phương pháp addTab nên thực hiện như sau:

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

Chú ý thứ tự của ba hoạt động cuối cùng. Trong ví dụ ban đầu, notifyDataSetChanged được gọi sau hàm mActionBar.addTab.

Thật không may, ngay khi bạn gọi số addTab trên ActionBar, tab đầu tiên bạn thêm sẽ tự động được chọn. Bởi vì điều này, sự kiện onTabSelected được kích hoạt và trong khi cố gắng truy xuất trang, nó trhows các IllegalStateException bởi vì nó nhận thấy một sự khác biệt giữa số mục dự kiến ​​và thực tế.

+0

Tôi đã tìm kiếm này trong một thời gian. Tôi là người duy nhất tìm thấy nó lẻ rằng lỗi đọc như thể tôi không gọi notifyDataSetChanged(), khi thực sự tôi cần phải thực hiện hành động (setCurrentItem trong trường hợp của tôi) Sau khi notifyDataSetChanged()? – wizurd

8

tôi cố định nó bằng cách callinig notifyDataSetChanged() một lần và ngay trước khi cuộc gọi tiếp theo của 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

Nội dung hay ngay tại đây ... cảm ơn! – worked

0

tôi đã cùng một vấn đề trong FragmentStatePager adapter. trong onResume() Khi reInitialize adpater và ViewPager, cùng một lỗi IllegalStateException sẽ được hiển thị. Giải pháp:

Khi thêm tab addtab, hãy chọn tab không được chọn bằng cách đặt setSelectselects thành false.

actionBar.addTab(tab,false); 

Tôi nghĩ rằng ngoại lệ xuất hiện vì trọng phương pháp onTabSelected() như sau

viewPager.setCurrentItem(tab.getPosition()); 

Vì vậy, khi gọi addTab() nó không nhận ra mà ViewPager và bộ chuyển đổi để thêm tab để.

3

tôi đã nhận được lỗi này như bạn bằng cách tham khảo các tab trong getCount():

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

Khi khởi tạo này nên cả hai được thông qua tại như một biến riêng biệt, hoặc máy nhắn tin phải được thiết lập sau bộ sưu tập đã được phổ biến/biến đổi.

0

Vấn đề của tôi không hoàn toàn giống nhau, nhưng ngữ cảnh tương tự.

Tôi có một AlertDialog được hiển thị trong bố cục có ViewPager và đang sử dụng AppCompatActivity. Tôi đã nhận được IllegalStateException và gặp sự cố khi xoay màn hình.

Nhờ câu trả lời từ câu trả lời @almisoft và @Zagorax, tôi đã thử gọi notifyDataSetChanged(); ngay trước khi tôi hiển thị hộp thoại và sự cố dường như đã biến mất.

1

hãy thử điều này. Tôi làm việc

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

Một dòng câu trả lời chỉ cần thêm viewpageadapter.notifyDataSetChanded()

Các vấn đề liên quan