- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我认为 FragmentStatePagerAdapter 在重写 getItemPosition(Object object)
以重新排序页面时行为不正确。
下面是一个简单的例子。在初始状态下,页面的顺序是{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
的源代码,可以通过在调用 set( )
在第 136 行。
如果我先滑动到页面 B,然后调用 getItem(2)
,创建页面 C,mFragments
现在的大小为 3 (这将防止上述崩溃立即发生)。然后我滑回页面 A,页面 C 被破坏,因为它应该是(因为它是 2 页,并且我使用默认的屏幕外页面限制 1)。现在,我调用 toggleState()
。页面 B 现已销毁。但是,不会重新创建页面 C!这意味着,当我现在向右滑动时,我会看到一个空白页面。
首先,很高兴知道我是否正确并且这些实际上是错误,或者我是否做错了什么。如果它们是错误,任何人都可以提出解决方法(除了自己调试和重建支持库)吗?肯定有人成功地覆盖了 getItemPosition(Object object)
(除了将所有内容都设置为 POSITION_NONE
)?
我正在使用支持库的当前版本 (10)。
最佳答案
查看 FragmentStatePagerAdapter 的来源,我确切地知道出了什么问题。 FragmentStatePagerAdapter 在 ArrayLists 中缓存 fragment 和保存状态:mFragments
和 mSavedState
。但是当 fragment 被重新排序时,没有重新排序 mFragments
和 mSavedState
元素的机制。因此,适配器会向寻呼机提供错误的 fragment 。
我已提交 an issue为此,并在问题上附加了一个固定的实现(NewFragmentStatePagerAdapter.java)。在修复中,我向 FragmentStatePagerAdapter 添加了一个 getItemId()
函数。 (这反射(reflect)了 FragmentPagerAdapter 中的重新排序实现。)始终按适配器位置存储 itemId 的数组。然后,在 notifyDataSetChanged()
中,适配器检查 itemIds 数组是否已更改。如果有,则 mFragments
和 mSavedState
会相应地重新排序。进一步的修改可以在 destroyItem()
、saveState()
和 restoreState()
中找到。
要使用这个类,getItemPosition()
和 getItemId()
必须与 getItem()
一致地实现。
关于android - 使用 getItemPosition(Object object) 对 FragmentStatePagerAdapter 中的页面重新排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12510404/
Android 的 PagerAdapter 类中的方法 getItemPosition 的文档指出它是: Called when the host view is attempting to det
我对 Fragment[State]PagerAdapter 有点疑惑。基本上我的问题是我需要根据屏幕方向更改 ViewPager 的内容( fragment )。我阅读了很多关于此的帖子,有些人说我
在 android 开发者博客上我读到了这个: If you’re trying to replace Views in your ViewPager, it isn’t enough just to
我有一个屏幕,其中包含来自设计支持库的新 TabLayout。我还有一个用于显示 fragment 的 ViewPager。此 fragment 根据选择的选项卡显示不同的 View 列表。 应用程序
我认为 FragmentStatePagerAdapter 在重写 getItemPosition(Object object) 以重新排序页面时行为不正确。 下面是一个简单的例子。在初始状态下,页面
我是一名优秀的程序员,十分优秀!