Snippet already added by IllegalStateException in viewpager

I am using a viewpager to display images. I just need three fragments basically: the previous image for preview, the current image displayed and the next image for preview. I would just like to display a preview of the previous and next images, it will change to the full image when the user actually holds it. So I decided to use only 3 fragments for this. Code below:

private class ImagePagerAdapter extends FragmentStatePagerAdapter implements ViewPager.OnPageChangeListener { private ImageFragment mImageFragment; private ImagePreviewFragment mPreviousPreviewFragment; private ImagePreviewFragment mNextPreviewFragment; public ImagePagerAdapter(FragmentManager fm, ImageFragment image, ImagePreviewFragment previous, ImagePreviewFragment next) { super(fm); mImageFragment = image; mPreviousPreviewFragment = previous; mNextPreviewFragment = next; } @Override public Fragment getItem(int position) { if (position == mPager.getCurrentItem()) { mImageFragment.display(position); return mImageFragment; } if (position < mPager.getCurrentItem()) { mPreviousPreviewFragment.display(position - 1); return mPreviousPreviewFragment; } mNextPreviewFragment.display(position + 1); return mNextPreviewFragment; } @Override public int getCount() { return 100; } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { Log.d(TAG, "onPageScrolled"); } @Override public void onPageSelected(final int position) { Log.d(TAG, "onPageSelected " + position); new Handler().postDelayed(new Runnable() { @Override public void run() { notifyDataSetChanged(); } }, 500); } @Override public void onPageScrollStateChanged(int state) { Log.d(TAG, "onPageScrollStateChanged " + state); } @Override public int getItemPosition(Object item) { return POSITION_NONE; //return POSITION_UNCHANGED; } } 

So I pre-created three fragments to display the previous / next preview and current image and return them for getItem (). I also notifydatasetchange () in onpageselected () to do all three positions to refresh the fragment when the user has moved to a new page.

But the problem is that he will throw

  Fragment already added IllegalStateException 

when fragments are added a second time. I think because it has been added before. I can create a new fragment every time, but I consider it wasteful. So, how can I reuse an already created fragment and just update them?

Thanks Simon

+5
source share
1 answer

FragmentStatePagerAdapter design suggests creating a new Fragment for each page ( see Google example ). And, unfortunately, you cannot read Fragment after it has been added to the FragmentManager (which is implicitly happening inside the adapter), so you encountered an exception. Thus, the official Google path is to create new fragments and allow them to be destroyed and recreated by the adapter.

But if you want to reuse pages and use an analogue of the ViewHolder template, you must stick to views instead of snippets. Views can be removed from the parent and reused, unlike fragments. Extend the PagerAdapter and implement instantiateItem() as follows:

 @Override public Object instantiateItem(ViewGroup container, final int position) { //determine the view type by position View view = viewPager.findViewWithTag("your_view_type"); if (view == null) { Context context = container.getContext(); view = LayoutInflater.from(context).inflate(R.layout.page, null); view.setTag("your_view_type"); } else { ViewGroup parent = (ViewGroup) item.getParent(); if (parent != null) { parent.removeView(item); } } processYourView(position, view); container.addView(view, MATCH); return view; } 

You need to add additional logic to determine the type of the view by position (since you have 3 types of views), I think you can figure it out.

+2
source

All Articles