片段已在viewpager中添加了IllegalStateException

use*_*560 5 illegalstateexception android-fragments android-viewpager fragmentstatepageradapter

我正在使用viewpager来显示图片.我基本上只需要三个片段:前一个要预览的图像,当前的显示图像和下一个要预览的图像.我想只显示上一张和下一张图片的预览,当用户实际滑动到它时,它会变为完整图像.所以我想只使用3个片段来实现这一点.代码如下:

    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;
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,我预先创建了三个片段来显示上一个/下一个预览和当前图像,并将它们返回给getItem().我还在onpageselected()中使用notifydatasetchange()来使用户滑动到新页面时更新片段的所有三个位置.

但问题是它会抛弃

    Fragment already added IllegalStateException
Run Code Online (Sandbox Code Playgroud)

当片段第二次添加时.我认为这是因为它之前已被添加.我每次都可以创建一个新的片段,但我觉得这很浪费.那么如何重用已经创建的片段并更新它们呢?

谢谢,西蒙

Dmi*_*ide 4

FragmentStatePagerAdapter设计建议为每个页面创建一个新的Fragment(请参阅 Google 的示例)。Fragment不幸的是,一旦将 a 添加到 a (适配器内部隐式发生的情况),您就无法读取 a FragmentManager,因此会出现异常。所以谷歌官方的方式是创建新的片段并让它们被适配器销毁并重新创建。

但是,如果您想重用页面并利用类似的 ViewHolder 模式,您应该坚持使用视图而不是片段。与片段不同,视图可以从其父级中删除并重新使用。像这样扩展PagerAdapter和实现:instantiateItem()

@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;
}
Run Code Online (Sandbox Code Playgroud)

您应该添加一些额外的逻辑来按位置确定视图类型(因为您有 3 种类型的视图),我认为您可以弄清楚。