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));
}
}
Run Code Online (Sandbox Code Playgroud)
我遇到了两个看似不正确的行为.
如果我立即呼叫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)
...
Run Code Online (Sandbox Code Playgroud)
查看源代码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 次 |
| 最近记录: |