Ugg*_*dle 24 android android-viewpager fragmentpageradapter
我相信当重写getItemPosition(Object object)以重新排序页面时,FragmentStatePagerAdapter的行为不正确.
下面是一个简单的例子.在初始状态中,页面的顺序是{A,B,C}.在呼叫时toggleState(),页面的顺序变为{A,C,B}.通过覆盖getItemPosition(Object object),我们确保正在查看的当前页面(A,B或C)不会更改.
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));
    }
}
我遇到了两个看似不正确的行为.
如果我立即呼叫toggleState()(在浏览页面A时,在刷到任何其他页面之前),应用程序崩溃了.
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,可以通过在第136行mFragments调用之前首先检查(如第113-115行)的大小来解决这个问题set().
如果我先刷到页面B,然后getItem(2)调用,则会创建页面C,mFragments现在大小为3(这样可以防止上面发生的崩溃).然后我滑回到页面A,并且页面C被销毁,因为它应该是(因为它是2页的距离,我使用默认的屏幕外页面限制为1).现在,我打电话toggleState().页面B现在已被销毁.但是,页面C不会重新创建!这意味着,当我现在向右滑动时,我得到一个空页面.
首先,我很高兴知道我是否正确,这些实际上是错误,或者我是否做错了什么.如果它们是错误,任何人都可以建议一个解决方法(除了自己调试和重建支持库)?当然有人必须getItemPosition(Object object)成功覆盖(除了设置一切POSITION_NONE)?
我正在使用支持库的当前版本(10).
Ugg*_*dle 37
看看FragmentStatePagerAdapter的来源,我弄清楚到底出了什么问题.FragmentStatePagerAdapter在ArrayLists中缓存片段和保存的状态:mFragments和mSavedState.但是,当片段重新排序,有没有机制来重新排序的元素mFragments和mSavedState.因此,适配器将向寻呼机提供错误的片段.
我已为此提交了一个问题,并附加了一个固定的实现(NewFragmentStatePagerAdapter.java).在修复中,我getItemId()向FragmentStatePagerAdapter 添加了一个函数.(这反映了FragmentPagerAdapter中的重新排序实现.)始终存储由适配器位置的itemIds数组.然后,在notifyDataSetChanged()适配器中检查itemIds数组是否已更改.如果是,那么mFragments和mSavedState相应地重新排序.进一步的修改中可以找到destroyItem(),saveState()和restoreState().
要使用这个类,getItemPosition()并且getItemId()必须以一贯的执行getItem().
| 归档时间: | 
 | 
| 查看次数: | 17189 次 | 
| 最近记录: |