我在我的一个应用程序中使用了FragmentStatePagerAdapter已有好几个月了,而且它已经完美无缺。我最近切换到IntelliJ IDEA并更新到ADT 22,现在适配器导致应用程序在应用程序试图销毁标签并创建新标签时强行关闭。
正常工作时,Activity会加载一系列标签。用户可以在它们之间滑动。所有这些仍然可以正常工作。
当用户在菜单中选择按钮时,应用应销毁这些标签并创建新标签。通常,这工作正常,但现在突然停止工作。这是代码:
/** TabsAdapter - Make Tabs Swipe-Able, Handle Fragments */
public static class TabsAdapter extends FragmentStatePagerAdapter 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;
}
} // end TabInfo
public TabsAdapter(SherlockFragmentActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
} // end TabsAdapter
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();
} // end addTab
public void removeTab(ActionBar.Tab tab) {
mTabs.remove(tab.getTag());
mActionBar.removeTab(tab);
notifyDataSetChanged();
}
@Override
public int getItemPosition(Object object) {
return TabsAdapter.POSITION_NONE;
}
@Override
public int getCount() {
return mTabs.size();
} // end getCount()
@Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
} // end getItem()
@Override
public void onPageScrolled(int position, float positionOffest, int postionOffsetPixels){
} // end onPageScrolled
@Override
public void onPageSelected(int position) {
mActionBar.setSelectedNavigationItem(position);
} // end onPageSelected
@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);
}
}
} // end onTabSelected
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft){} // end onTabUnselected
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft){} // end onTabReselected
@Override
public void onPageScrollStateChanged(int arg0) {}
} // end TabsAdapter
在onCreate()期间,我调用一个方法,让它称之为CreateTabs1(),它成功构建了标签,用户可以滑动。只有当寻呼机试图销毁标签并创建新标签时,它才会突然失败,即使我再次调用CreateTabs1()也是如此。同样,这之前总是完美无缺。
这是日志:
05-25 23:41:24.857: ERROR/AndroidRuntime(27290): FATAL EXCEPTION: main
java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 11, found: 10 Pager id: com.######:id/pager Pager class: class android.support.v4.view.ViewPager Problematic adapter: class com.#####.######.#####$TabsAdapter
at android.support.v4.view.ViewPager.populate(ViewPager.java:959)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:548)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:507)
at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:488)
at com.#####.#####.#####$TabsAdapter.onTabSelected(#####.java:215)
at com.actionbarsherlock.internal.app.ActionBarWrapper$TabWrapper.onTabSelected(ActionBarWrapper.java:356)
at com.android.internal.app.ActionBarImpl.selectTab(ActionBarImpl.java:570)
at com.android.internal.app.ActionBarImpl.removeTabAt(ActionBarImpl.java:544)
at com.android.internal.app.ActionBarImpl.removeTab(ActionBarImpl.java:520)
at com.actionbarsherlock.internal.app.ActionBarWrapper.removeTab(ActionBarWrapper.java:409)
at com.#####.#####.#####$TabsAdapter.removeTab(#####.java:181)
at com.#####.#####.#####.tabDrop(#####.java:381)
at com.#####.#####.#####.onOptionsItemSelected(#####.java:459)
at android.support.v4.app.Watson.onMenuItemSelected(Watson.java:118)
at com.actionbarsherlock.ActionBarSherlock.callbackOptionsItemSelected(ActionBarSherlock.java:603)
at com.actionbarsherlock.internal.ActionBarSherlockNative.dispatchOptionsItemSelected(ActionBarSherlockNative.java:93)
at com.actionbarsherlock.app.SherlockFragmentActivity.onMenuItemSelected(SherlockFragmentActivity.java:205)
at com.android.internal.policy.impl.PhoneWindow.onMenuItemSelected(PhoneWindow.java:980)
at com.android.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:735)
at com.android.internal.view.menu.SubMenuBuilder.dispatchMenuItemSelected(SubMenuBuilder.java:81)
at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:149)
at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:874)
at com.android.internal.view.menu.MenuPopupHelper.onItemClick(MenuPopupHelper.java:156)
at android.widget.AdapterView.performItemClick(AdapterView.java:298)
at android.widget.AbsListView.performItemClick(AbsListView.java:1100)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:2749)
at android.widget.AbsListView$1.run(AbsListView.java:3423)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
答案 0 :(得分:21)
在ADT 22之后,PagerAdapter在调用getCount()之前调用notifyDataSetChanged()非常严格。它显然跟踪它认为计数应该是什么,如果这与getCount()返回的不一样,则抛出此异常。因此,解决方案只是在每次数据大小发生变化时调用适配器上的notifyDataSetChanged()。
在我的情况下,我有一个后台任务,正在创建一个数据数组。数组填满后,我在onPostExecute()中调用notifyDataSetChanged()。当我在onPostExecute()中有一个没有调用notifyDataSetChanged()的路径时,我得到了异常。
答案 1 :(得分:1)
将notifyDataSetChanged();
方法直接放在方法下方,以便向寻呼机添加/删除页面确实有效。谢谢@Ninjalan
答案 2 :(得分:0)
您可以在所有添加/删除标签逻辑之前调用ViewPager.setAdapter(null)
,最后重新分配更新的适配器。解决了我的烦恼。
mPager.setAdapter(null);
mTabHost.clearAllTabs();
mTabHost.addTab(...);
mTabHost.addTab(...);
mTabHost.addTab(...);
mPager.setAdapter(YOUR_UPDATED_ADAPTER_HERE);
答案 3 :(得分:0)
Youtry set Codeing myViewPagerAdapter.notifyDataSetChanged();
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
feedItemComics = (FeedItemComics) getArguments().getSerializable( DESCRIBABLE_KEY);
feedItemComics.getTitle();
feedItemComics.getLast_modified();
sceneNo.setText(feedItemComics.getScene_no());
title.setText(feedItemComics.getTitle());
// Logger.Log("feedItemComics.getThumbnail", feedItemComics.getLast_modified());
Logger.Log("feedItemComics.getTitle", feedItemComics.getTitle());
itemComicses = (ArrayList<FeedItemComics>) getArguments().getSerializable("images");
// feedItemList = (ArrayList<FeedItemComics>) getArguments().getSerializable("images");
selectedPosition = getArguments().getInt("position");
Logger.Log("itemComicses size", String.valueOf(itemComicses.size()));
Logger.Log("selectedPosition", String.valueOf(selectedPosition));
myViewPagerAdapter.notifyDataSetChanged();
clickPrevious.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(viewPager.getCurrentItem()-1 < itemComicses.size()+1 ){
viewPager.setCurrentItem(viewPager.getCurrentItem()-1);
Logger.Log("position " , String.valueOf(viewPager.getCurrentItem()-1));
}
}
});
clickNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(viewPager.getCurrentItem()+1 < itemComicses.size() ){
viewPager.setCurrentItem(viewPager.getCurrentItem()+1);
Logger.Log("position " , String.valueOf(viewPager.getCurrentItem()+1));
}
}
});
}