Android documentation here )から取得したViewPager
タブを使用したActionBar
の例を使用しています。
残念ながら、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()の呼び出しで終了する必要があります。
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);
}
最後の3つの操作の順序に注意してください。元の例では、notifyDataSetChanged
はmActionBar.addTab
関数の後に呼び出されました。
残念ながら、addTab
でActionBar
を呼び出すとすぐに、追加した最初のタブが自動的に選択されます。このため、onTabSelected
イベントが発生し、ページを取得しようとしているときに、予想されるアイテムカウントと実際のアイテムカウントの不一致に気付くため、IllegalStateException
をスローします。
一度getin()を呼び出す直前に、callinig notifyDataSetChanged()で修正しました。
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();
}
インスタンス化するとき、これは別の変数として渡すか、ページャーをセットアップする必要がありますafterコレクションが移入/変更されました。
これを試して。私は働いた
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();
}
SetOffscreenPageLimitとgetCountの値が一致することを確認してください。一致しない場合、このエラーが発生します。
mViewPager.setOffscreenPageLimit(MAX_TABS);
public class SectionsPagerAdapter extends FragmentPagerAdapter {
...
@Override
public int getCount() {
return MAX_TABS;
}
私の問題はまったく同じではありませんでしたが、コンテキストは似ていました。
ViewPagerがあり、AppCompatActivityを使用しているレイアウトにAlertDialogが表示されています。 IllegalStateExceptionが発生し、画面を回転させるとクラッシュしました。
回答@almisoftと@Zagoraxからの回答のおかげで、ダイアログを表示する直前にnotifyDataSetChanged();
を呼び出してみましたが、問題は解消されたようです。
Viewpager.setAdapter(adapter);を呼び出します。配列リストに項目を追加した後。
public Object instantiateItem(ViewGroup container、int position)メソッドが呼び出されるアダプターファイルにこの行を追加します
((ViewPager)コンテナー).addView(view);戻りビュー;
FragmentStatePager
アダプターでも同じ問題が発生しました。 in onResume()
adpaterとViewPager
を再初期化すると、同じエラーIllegalStateException
が表示されます。ソリューション:
タブaddtab
を追加する場合、setSelected paramsをfalseに設定して、選択しないタブを選択します。
_ actionBar.addTab(tab,false);
_
onTabSelected()
メソッドを次のようにオーバーライドしたため、例外が発生したと思います
_ viewPager.setCurrentItem(tab.getPosition());
_
そのため、addTab()
を呼び出したときに、タブを追加するviewPagerとアダプターを認識しませんでした。