【问题标题】:Fragment already added IllegalStateException in viewpagerFragment 已经在 viewpager 中添加了 IllegalStateException
【发布时间】:2020-04-22 23:37:06
【问题描述】:

我正在使用 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;
    }
}

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

但问题是它会扔掉

    Fragment already added IllegalStateException

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

谢谢, 西蒙

【问题讨论】:

    标签: android-fragments android-viewpager illegalstateexception fragmentstatepageradapter


    【解决方案1】:

    FragmentStatePagerAdapter 设计建议为每个页面创建一个新的Fragment (see Google's example)。不幸的是,一旦将 Fragment 添加到 FragmentManager (适配器内部隐含发生的事情),您就无法读取它,因此您得到了例外。所以官方的 Google 方式是创建新的 Fragment 并让它们被适配器销毁并重新创建。

    但是,如果您想重用页面并使用类似于 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;
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-22
      • 2021-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-09
      • 1970-01-01
      相关资源
      最近更新 更多