重新安排使用getItemPosition在FragmentStatePagerAdapter页(Object对象) [英] reorder pages in FragmentStatePagerAdapter using getItemPosition(Object object)

查看:3291
本文介绍了重新安排使用getItemPosition在FragmentStatePagerAdapter页(Object对象)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我相信FragmentStatePagerAdapter不正确重写时表现得 getItemPosition(Object对象)与重新排序的页面的目的。

I believe that FragmentStatePagerAdapter does not behave correctly when overriding getItemPosition(Object object) with the purpose of reordering the pages.

下面是一个简单的例子。在初始状态中,页面的顺序是{A,B,C}。当打电话 toggleState()的页面就会变为{A,C,B}的顺序。通过覆盖 getItemPosition(Object对象),我们确保当前正在浏览的页面(A,B或C)不会改变。

Below is a simple example. In the initial state, the order of the pages is {A, B, C}. Upon calling toggleState(), the order of the pages changes to {A, C, B}. By overriding getItemPosition(Object object), we ensure that the current page being viewed (A, B, or C) does not change.

public static class TestPagerAdapter extends FragmentStatePagerAdapter {
    private boolean mState = true;

    public TestPagerAdapter(FragmentManager fragmentManager) {
        super(fragmentManager);
    }

    @Override
    public int getCount() {
        return 3;
    }

    private void toggleState() {
        mState = !mState;
        notifyDataSetChanged();
    }

    private String getLabel(int position) {
        switch (position) {
            case 0:
                return "A";
            case 1:
                return mState ? "B" : "C";
            default:
                return mState ? "C" : "B";
        }
    }

    @Override
    public int getItemPosition(Object object) {
        String label = ((TestFragment) object).getLabel();
        if (label.equals("A")) {
            return 0;
        } else if (label.equals("B")) {
            return mState ? 1 : 2;
        } else {
            return mState ? 2 : 1;
        }
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return getLabel(position);
    }

    @Override
    public Fragment getItem(int position) {
        return TestFragment.newInstance(getLabel(position));
    }
}

我也遇到过两个独立的行为,这似乎不正确。

I have encountered two separate behaviours which seem incorrect.

  1. 如果我立即打电话 toggleState()(在查看网页A,刷卡任何其他页之前),应用程序崩溃。

  1. If I immediately call toggleState() (while viewing page A, before swiping to any other page), the app crashes.

java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2
  at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
  at java.util.ArrayList.set(ArrayList.java:477)
  at android.support.v4.app.FragmentStatePagerAdapter.destroyItem(FragmentStatePagerAdapter.java:136)
  at android.support.v4.view.ViewPager.populate(ViewPager.java:867)
  at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:469)
  at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:441)
  at android.support.v4.view.ViewPager.dataSetChanged(ViewPager.java:766)
  at android.support.v4.view.ViewPager$PagerObserver.onChanged(ViewPager.java:2519)
  at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
  at android.support.v4.view.PagerAdapter.notifyDataSetChanged(PagerAdapter.java:276)
  at com.ugglynoodle.test.testfragmentstatepageradapter.MainActivity$TestPagerAdapter.toggleState(MainActivity.java:55)
  ...

看着 FragmentStatePagerAdapter 的来源,这将是固定首先检查 mFragments 的大小(如调用设置()的行136前行113-115)。

Looking at the source of FragmentStatePagerAdapter, this would be fixed by first checking the size of mFragments (as in lines 113-115) before calling set() in line 136.

如果我第一次刷到网页B,那么的getItem(2)之称,是创建网页C和 mFragments 现在有3大小(这将prevent上面的碰撞发生在某一时刻)。然后我刷卡返回页面A和页面C被破坏,因为它应该是(因为它是2页了,而我使用的是默认的屏幕外的1页数限制)。现在,我称之为 toggleState()。页乙现在破坏。然而,网页c不是重建!这意味着,当我现在向右滑动,我得到一个空白页。

If I first swipe to page B, then getItem(2) is called, page C is created, and mFragments now has a size of 3 (this will prevent the crash above from happening in a moment). Then I swipe back to page A, and page C is destroyed, as it should be (since it is 2 pages away, and I'm using the default offscreen page limit of 1). Now, I call toggleState(). Page B is now destroyed. However, page C is NOT recreated! This means, when I now swipe to the right, I get an empty page.

首先,这将是很好知道我是否正确,这些其实都是虫子,还是我做错了什么。如果是这样的错误,任何人都可以提出一个解决办法(比调试和重建的支持库本人除外)?当然,有人必须重写 getItemPosition(Object对象)成功(除了设置一切 POSITION_NONE )?

First, it would be nice to know whether I'm correct and these are in fact bugs, or whether I'm doing something wrong. If they are bugs, can anyone suggest a workaround (other than debugging and rebuilding the support library myself)? Surely somebody must have overridden getItemPosition(Object object) successfully (apart from setting everything to POSITION_NONE)?

我使用的是支持库的当前版本(10)。

I am using the current revision (10) of the support library.

推荐答案

看着FragmentStatePagerAdapter的来源,我想通了,到底是怎么回事错了。该FragmentStatePagerAdapter缓存片段,并保存州的ArrayList mFragments mSavedState 。但是,当片段重新排序,有没有机制来重新排序的 mFragments mSavedState 的元素。因此,该适配器将提供错误的片段到寻呼机

Looking at the source of FragmentStatePagerAdapter, I figured out exactly what is going wrong. The FragmentStatePagerAdapter caches the fragments and saved states in ArrayLists: mFragments and mSavedState. But when the fragments are reordered, there's no mechanism for reordering the elements of mFragments and mSavedState. Therefore, the adapter will provide the wrong fragments to the pager.

我已经申请此问题,并附加了固定的实现(NewFragmentStatePagerAdapter.java)这个问题。在此修复程序,我添加了一个 getItemId()函数FragmentStatePagerAdapter。 (这反映在FragmentPagerAdapter的重新排序的实施。)的itemIds的由适配器位置的数组存储在任何时候。然后,在 notifyDataSetChanged(),如果itemIds阵列已经改变了适配器的检查。如果是,那么 mFragments mSavedState 相应地重新排序。进一步的修改可以在 destroyItem找到() saveState和() restoreState()

I've filed an issue for this, and attached a fixed implementation (NewFragmentStatePagerAdapter.java) to the issue. In the fix, I've added a getItemId() function to FragmentStatePagerAdapter. (This mirrors the reordering implementation in FragmentPagerAdapter.) An array of the itemIds by adapter position is stored at all times. Then, in notifyDataSetChanged(), the adapter checks if the itemIds array has changed. If it has, then mFragments and mSavedState are reordered accordingly. Further modifications can be found in destroyItem(), saveState() and restoreState().

要使用这个类, getItemPosition() getItemId()必须用一贯的执行的getItem()

To use this class, getItemPosition() and getItemId() must be implemented consistently with getItem().

这篇关于重新安排使用getItemPosition在FragmentStatePagerAdapter页(Object对象)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆