2013-05-26 29 views
16

Tôi đã sử dụng một FragmentStatePagerAdapter trong một trong các ứng dụng của tôi trong nhiều tháng và nó đã hoạt động hoàn hảo. Gần đây tôi đã chuyển sang IntelliJ IDEA và cập nhật lên ADT 22 và giờ đây Bộ điều hợp khiến ứng dụng buộc phải đóng khi ứng dụng cố gắng phá hủy các tab và tạo các tab mới.FragmentStatePagerAdapter ngừng hoạt động sau khi cập nhật lên ADT 22?

Khi hoạt động chính xác, Hoạt động sẽ tải một loạt các tab. Người dùng có thể vuốt giữa chúng. Tất cả điều này vẫn hoạt động chính xác.

Ứng dụng sẽ hủy các tab này và tạo tab mới khi người dùng chọn nút trong menu. Thông thường, điều này hoạt động tốt nhưng bây giờ nó đột nhiên ngừng hoạt động. Đây là mã:

/** 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 

Trong khi onCreate(), tôi gọi phương thức, hãy gọi nó là CreateTabs1() và tạo thành công các tab và người dùng có thể vuốt. Chỉ khi máy nhắn tin cố gắng phá hủy các tab và tạo ra những cái mới mà bây giờ nó không thành công đột ngột, ngay cả khi tôi gọi lại là CreateTabs1(). Một lần nữa, điều này luôn luôn làm việc hoàn hảo trước đây.

Đây là nhật ký:

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

thử này http://stackoverflow.com/questions/16636039/java-lang-classnotfoundexception-after-changing-nothing-in-the-project-but-upgra/16636127#16636127 nếu nó giúp – Raghunandan

+0

Is có một cách để làm sạch một dự án và xây dựng lại nó trong IntelliJ? Đây có vẻ là một giải pháp cho người dùng Eclipse. Ngoài ra, nếu nó giúp, các ứng dụng xây dựng một cách chính xác và nếu không chạy và hoạt động tốt. Điều này dường như không chỉ bây giờ. – Ninjalan

+0

nope tôi không sử dụng Intellij. tôi không nhận thức được rằng – Raghunandan

Trả lời

21

Sau ADT 22 PagerAdapter đã nhận được rất nghiêm ngặt về gọi notifyDataSetChanged() trước khi gọi getCount(). Nó rõ ràng theo dõi những gì nó nghĩ rằng đếm nên được và nếu điều này là không giống như những gì getCount() trả về nó ném ngoại lệ này. Vì vậy, giải pháp chỉ đơn giản là để gọi notifyDataSetChanged() trên bộ điều hợp mỗi khi kích thước của dữ liệu thay đổi.

Trong trường hợp của tôi, tôi có một tác vụ nền đang tạo một mảng dữ liệu. Sau khi mảng được lấp đầy, tôi gọi notifyDataSetChanged() trong onPostExecute(). Khi tôi đã có một con đường trong onPostExecute() mà không gọi notifyDataSetChanged() tôi đã nhận được ngoại lệ.

+0

Hm, có ý nghĩa, nhưng tôi đang gặp khó khăn khi cố gắng quyết định nơi khác tôi nên notiftyDataSetChanged(). Tôi gọi phương thức mỗi khi một tab được thêm vào hoặc bị xóa. Tôi nghĩ đây sẽ là lần duy nhất kích thước của dữ liệu thay đổi, đúng không? – Ninjalan

+1

Tôi thấy rằng việc thêm notifyDataSetChanged(); ngay trên vòng lặp for on onTabSelected() giải quyết vấn đề nhưng nó làm chậm ứng dụng xuống vô cùng. Có một nơi thông minh hơn mà tôi nên đặt nó không? – Ninjalan

+1

Cập nhật: Tôi thấy rằng di chuyển notifyDataSetChanged(); trong các phương pháp thêm và xóa tab đã làm các trick. Đó là phương pháp cuối cùng để chạy trong mã ban đầu của tôi, nhưng đặt nó trực tiếp bên dưới phương thức để thêm/xóa trang vào máy nhắn tin vì một số lý do đã làm việc. Nó vẫn còn hơi chậm nhưng nó hoạt động! – Ninjalan

0

Bạn có thể gọi ViewPager.setAdapter(null) ngay trước tất cả thêm/xóa tab logic và ở cuối gán lại với bộ điều hợp đã cập nhật. Giải quyết những rắc rối của tôi.

mPager.setAdapter(null); 
mTabHost.clearAllTabs(); 
mTabHost.addTab(...); 
mTabHost.addTab(...); 
mTabHost.addTab(...); 
mPager.setAdapter(YOUR_UPDATED_ADAPTER_HERE); 
1

đặt phương thức trực tiếp bên dưới phương pháp thêm/xóa trang vào máy nhắn tin đã hoạt động. Cảm ơn @Ninjalan

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

     } 
    }); 

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