【问题标题】:issues while add or delete of pages at random positions in FragmentStatePagerAdapter dynamically在 FragmentStatePagerAdapter 中的随机位置动态添加或删除页面时出现问题
【发布时间】:2015-08-20 13:09:20
【问题描述】:

我在 stakcoverflow 和 google 的 android 文档中花了很多时间在有关在 FragmentStatePagerAdapter 的随机位置添加或删除页面的相关问题/答案上。
它工作正常,但在一种情况下失败。
可行的方案 1:
添加,比如说,4 页(片段)。
删除位于位置 3 的最后一个位置的页面。
再次在页面末尾添加一页。
删除位于位置 3 的最后一个位置的页面。
……我重复这个步骤,它工作得很好。

但是场景 2 失败了:
添加,比如说,4 页(片段)。
删除除最后一个位置以外的任何页面,例如位置 2。工作正常。页面不再可见。
再次在页面末尾添加一页。在这里失败..我看到空白页。

我确实在一定程度上对其进行了分析,我发现 getItem() 失败时没有被调用。因为 getItem() 是创建并返回新片段的那个,所以它没有得到新片段,所以它显示为空白。我看到了 instantiateItem() 的实现,并观察到如果可用片段的大小大于为其创建片段所请求的位置,则不会调用 getItem()。但不确定它何时发生或如何发生。

这是我的适配器中的 getItem() 和 getItemPosition()。我有我自己的一组 ArrayList 片段(FragmentStatePagerAdapter 维护它自己的片段列表集)...... mFragments 是在下面的代码中。在我调用 notifyDataItemChanged() 后,我观察到。

@Override
public int getItemPosition(Object object) {
    if (object instanceof InnerFragment) {
        if (!mFragments.contains(object)) {
            Log.d(TAG, "getItemPosition Frag " + object + " is REMOVED and item count is " + MainFragment.mPager.getChildCount());
            return POSITION_NONE;
        } else {
            Log.d(TAG, "getItemPosition Frag " + object + " is AVAILABLE and item count is " + MainFragment.mPager.getChildCount());
            Log.d(TAG, "getItemPosition .....position of this fragment is : " + mFragments.indexOf(object));
            return mFragments.indexOf(object);
        }
    }
    Log.d(TAG, "getItemPosition object is not InnerFragment..");
    return super.getItemPosition(object);
}

@Override
public Fragment getItem(int position) {
    Log.d(TAG, "getItem for position " + position + "..create NEW FRAG and item count is " + MainFragment.mPager.getChildCount());
    return createNewPage(position);
}

如果您有任何线索,请花几分钟时间帮助我。 下面是日志 sn-ps。第一个是当我删除了第三个位置的页面(这是页面的中间,而不是最后一页)。第二个是当我尝试添加新页面时。您可以观察到当我在第二个日志 sn-p 中添加页面时没有调用 getItem() ..

08-20 12:09:55.062    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   Places/count before handlePlaces : 6 and fragments : [InnerFragment{3e50591d #0 id=0x7f10008d}, InnerFragment{ccaf792 #1 id=0x7f10008d}, InnerFragment{16c61563 #2 id=0x7f10008d}, InnerFragment{3a6d7560 #3 id=0x7f10008d}, InnerFragment{229e6a19 #4 id=0x7f10008d}, InnerFragment{2a1cfade #5 id=0x7f10008d}]
08-20 12:09:55.062    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   Place deleted : 110665902
08-20 12:09:55.072    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   Places/count after handlePlaces : 5 and fragments : [InnerFragment{3e50591d #0 id=0x7f10008d}, InnerFragment{ccaf792 #1 id=0x7f10008d}, InnerFragment{16c61563 #2 id=0x7f10008d}, InnerFragment{229e6a19 #4 id=0x7f10008d}, InnerFragment{2a1cfade #5 id=0x7f10008d}]
08-20 12:09:55.072    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition Frag InnerFragment{3e50591d #0 id=0x7f10008d} is AVAILABLE and item count is 6
08-20 12:09:55.072    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition .....position of this fragment is : 0
08-20 12:09:55.072    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition Frag InnerFragment{ccaf792 #1 id=0x7f10008d} is AVAILABLE and item count is 6
08-20 12:09:55.072    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition .....position of this fragment is : 1
08-20 12:09:55.072    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition Frag InnerFragment{16c61563 #2 id=0x7f10008d} is AVAILABLE and item count is 6
08-20 12:09:55.072    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition .....position of this fragment is : 2

08-20 12:09:55.072    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition Frag InnerFragment{3a6d7560 #3 id=0x7f10008d} is REMOVED and item count is 6
08-20 12:09:55.072    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   destroyItem object InnerFragment{3a6d7560 #3 id=0x7f10008d}to be rmeoved from 3

08-20 12:09:55.072    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition Frag InnerFragment{229e6a19 #4 id=0x7f10008d} is AVAILABLE and item count is 6
08-20 12:09:55.072    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition .....position of this fragment is : 3
08-20 12:09:55.072    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition Frag InnerFragment{2a1cfade #5 id=0x7f10008d} is AVAILABLE and item count is 6
08-20 12:09:55.072    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition .....position of this fragment is : 4




08-20 12:10:10.152    3919-3919/ com.example.pack D/MainActivity﹕   all received for Place{placeId=119680744, placeName='Moskva', localName='null', latitude=55.75222, longitude=37.61556, moh=150, countryId=1426, categoryId=1552, categoryName='Hovedstad', country='Russia', priority=0, adm1='null', adm2='Moscow'}
08-20 12:10:15.152    3919-3919/ com.example.pack D/MainActivity﹕   all received for Place{placeId=113259163, placeName='Stockholm', localName='null', latitude=59.33258, longitude=18.0649, moh=21, countryId=428, categoryId=1552, categoryName='Hovedstad', country='Sweden', priority=0, adm1='Stockholm', adm2='Stockholm municipality'}
08-20 12:10:25.112    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   Places/count before handlePlaces : 5 and fragments : [InnerFragment{3e50591d #0 id=0x7f10008d}, InnerFragment{ccaf792 #1 id=0x7f10008d}, InnerFragment{16c61563 #2 id=0x7f10008d}, InnerFragment{229e6a19 #4 id=0x7f10008d}, InnerFragment{2a1cfade #5 id=0x7f10008d}]
08-20 12:10:25.112    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   New Place added : 105109562
08-20 12:10:25.112    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   Places/count after handlePlaces : 6 and fragments : [InnerFragment{3e50591d #0 id=0x7f10008d}, InnerFragment{ccaf792 #1 id=0x7f10008d}, InnerFragment{16c61563 #2 id=0x7f10008d}, InnerFragment{229e6a19 #4 id=0x7f10008d}, InnerFragment{2a1cfade #5 id=0x7f10008d}]
08-20 12:10:25.112    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition Frag InnerFragment{3e50591d #0 id=0x7f10008d} is AVAILABLE and item count is 5
08-20 12:10:25.112    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition .....position of this fragment is : 0
08-20 12:10:25.112    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition Frag InnerFragment{ccaf792 #1 id=0x7f10008d} is AVAILABLE and item count is 5
08-20 12:10:25.112    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition .....position of this fragment is : 1
08-20 12:10:25.112    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition Frag InnerFragment{16c61563 #2 id=0x7f10008d} is AVAILABLE and item count is 5
08-20 12:10:25.112    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition .....position of this fragment is : 2
08-20 12:10:25.112    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition Frag InnerFragment{229e6a19 #4 id=0x7f10008d} is AVAILABLE and item count is 5
08-20 12:10:25.112    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition .....position of this fragment is : 3
08-20 12:10:25.112    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition Frag InnerFragment{2a1cfade #5 id=0x7f10008d} is AVAILABLE and item count is 5
08-20 12:10:25.112    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   getItemPosition .....position of this fragment is : 4

08-20 12:10:25.122    3919-3919/ com.example.pack D/MyFragStatePagerAdapter﹕   instantiateItem for position 5 and item count is 5

【问题讨论】:

    标签: android adapter fragmentstatepageradapter


    【解决方案1】:

    我无法猜测这将是一个框架问题。但是在我花了很多时间分析它之后,我发现 FragmentStatePagerAdapter 中的 destroyItem() 并没有删除 getItemPosition() 返回 POSITION_NONE 的片段。它分配 null 但不会删除该项目。下面是来自原始 FragmentStatePagerAdapter 的方法。你看我已经添加了两行代码来明确删除片段。

        public void destroyItem(ViewGroup container, int position, Object object) {
            Fragment fragment = (Fragment)object;
            if(this.mCurTransaction == null) {
                this.mCurTransaction = this.mFragmentManager.beginTransaction();
            }
    
            while(this.mSavedState.size() <= position) {
                this.mSavedState.add(null);
            }
    
            this.mSavedState.set(position, this.mFragmentManager.saveFragmentInstanceState(fragment));
            this.mFragments.set(position, null);
    
            /***** Below are the two lines I have added  
            in addition to this original method from Android. ******/
            this.mFragments.remove(position);
            this.mSavedState.remove(position);
    
            this.mCurTransaction.remove(fragment);
        }
    

    我可以在日志中清楚地看到,删除页面后的页面索引未正确重新排序。

    InnerFragment{3e50591d #0 id=0x7f10008d}
    InnerFragment{ccaf792 #1 id=0x7f10008d}
    InnerFragment{16c61563 #2 id=0x7f10008d}
    InnerFragment{229e6a19 #4 id=0x7f10008d}
    InnerFragment{2a1cfade #5 id=0x7f10008d}
    

    我删除了第三个位置。上面是容器中的片段列表,您可以在其中看到索引#3 丢失。那是因为有一个元素是 null..它没有被完全删除,但如果你观察它,它只是原始代码引用的 null。
    我的情况是我应该能够删除任何页面,并且应该能够在最后添加一个新页面。
    因此,我使用上面的destroyItem() 方法中的行显式删除了对象。它奏效了。

    最后但同样重要的是,我在得到答案后找到了这个链接。请参阅此https://code.google.com/p/android/issues/detail?id=37990。许多开发人员似乎都遇到了多个问题,但对于他们的特定场景,他们也有解决方案。查找您的场景是否涵盖在那里。如果不行你可以照我做的..把完整的 FragmentStatePagerAdapter.java 解压出来,根据需要修改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多