FragmentStatePagerAdapter刷新无效问题

FragmentStatePagerAdapter虽然过时,但是老项目使用,问题也不大。

背景:首页tab+viewPager会根据用户偏好来改变展示顺序,但是当用户改变偏好后,调用fragmentStatePagerAdapter.nitifyDataSetChanged()时,发现刷新有时不生效,所以看源码

直接去ViewPager的dataSetChanged(),函数,为什么直接看这个?(自己看nitifyDataSetChanged()的实现)

void dataSetChanged() {
    // This method only gets called if our observer is attached, so mAdapter is non-null.

    final int adapterCount = mAdapter.getCount();
    mExpectedAdapterCount = adapterCount;
    boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1
            && mItems.size() < adapterCount;
    int newCurrItem = mCurItem;

    boolean isUpdating = false;
    for (int i = 0; i < mItems.size(); i++) {
        final ItemInfo ii = mItems.get(i);
        final int newPos = mAdapter.getItemPosition(ii.object);

        if (newPos == PagerAdapter.POSITION_UNCHANGED) {
            continue;
        }

        if (newPos == PagerAdapter.POSITION_NONE) {
            mItems.remove(i);
            i--;

            if (!isUpdating) {
                mAdapter.startUpdate(this);
                isUpdating = true;
            }

            mAdapter.destroyItem(this, ii.position, ii.object);
            needPopulate = true;

            if (mCurItem == ii.position) {
                // Keep the current item in the valid range
                newCurrItem = Math.max(0, Math.min(mCurItem, adapterCount - 1));
                needPopulate = true;
            }
            continue;
        }

        if (ii.position != newPos) {
            if (ii.position == mCurItem) {
                // Our current item changed position. Follow it.
                newCurrItem = newPos;
            }

            ii.position = newPos;
            needPopulate = true;
        }
    }

    if (isUpdating) {
        mAdapter.finishUpdate(this);
    }

    Collections.sort(mItems, COMPARATOR);

    if (needPopulate) {
        // Reset our known page widths; populate will recompute them.
        final int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if (!lp.isDecor) {
                lp.widthFactor = 0.f;
            }
        }

        setCurrentItemInternal(newCurrItem, false, true);
        requestLayout();
    }
}

关键是newPos的获取和newPos的判断,发现只有newPos == POSITION_NONE的时候,item才会改变,所以看mAdapter.getItemPosition的定义

/**
 * Called when the host view is attempting to determine if an item's position
 * has changed. Returns {@link #POSITION_UNCHANGED} if the position of the given
 * item has not changed or {@link #POSITION_NONE} if the item is no longer present
 * in the adapter.
 *
 * <p>The default implementation assumes that items will never
 * change position and always returns {@link #POSITION_UNCHANGED}.
 *
 * @param object Object representing an item, previously returned by a call to
 *               {@link #instantiateItem(View, int)}.
 * @return object's new position index from [0, {@link #getCount()}),
 *         {@link #POSITION_UNCHANGED} if the object's position has not changed,
 *         or {@link #POSITION_NONE} if the item is no longer present.
 */
public int getItemPosition(@NonNull Object object) {
    return POSITION_UNCHANGED;
}

空实现,但是注释很明白,当item的position没发生变化的时候返回POSITION_UNCHANGED,发生变化时返回POSITION_NONE,结合上边的newPos的判断逻辑,我们可以重写getItemPosition方法

class HomePageAdapter(var data: List<BaseNavigationFragment>, fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) {

    var oldCount = data.size
    var changeSort = false
        set(value) {
            field = value
            oldCount = data.size
        }

    override fun getItem(position: Int): Fragment = data[position]

    override fun getItemPosition(item: Any): Int {
        if (changeSort && oldCount > 0) {
            oldCount--
            return POSITION_NONE
        }
        return POSITION_UNCHANGED
    }

    override fun getCount(): Int  = data.size
}

顺序发生变化时直接返回POSITION_NONE,为了不影响其他正常流程中的逻辑,此处设置了oldCount,当变化发生后,所有的item都走一遍之后,就返回POSITION_UNCHANGED(因为我们的业务逻辑中只有一处会发生顺序变化!)

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值