ViewPager中动态删除Fragment的方法

问题所在:我们在数据源发生改变时,调用notifyDataSetChanged() 方法,发现界面没有变化

原因分析:

追踪到ViewPager 的 dataSetChanged()方法,此方法用于刷新界面,看看具体的实现:

...
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) {
        ...
        continue;
    }
    ...
}
...

官方给出了解释:

Called when the host view is attempting to determine if an item’s position has changed. Returns POSITION_UNCHANGED if the position of the given item has not changed or POSITION_NONE if the item is no longer present in the adapter.The default implementation assumes that items will never change position and always returns POSITION_UNCHANGED.

大致的意思为:

如果 Item 的位置如果没有发生变化,则返回 POSITION_UNCHANGED。如果返回了 POSITION_NONE,表示该位置的 Item 已经不存在了。默认的实现是假设 Item 的位置永远不会发生变化,而返回 POSITION_UNCHANGED。(参考自:追溯源码解决android疑难有关问题1-Viewpager之notifyDataSetChanged无刷新

简单的解决办法:

重写PagerAdapter的getItemPosition(Object object) 方法,将返回值固定为 POSITION_NONE。

上代码:

@Override
public int getItemPosition(Object object) {
    return POSITION_NONE;
}

//如果使用的不是FragmentPagerAdapter,需要重写此方法
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    // 把 Object 强转为 View,然后将 view 从 ViewGroup 中清除
    container.removeView((View) object);
}

问题到此还没有结束,原因在于我是用的是FragmentPagerAdapter,在这里我们还得去跟源码,重点在于FragmentPagerAdapter中的instantiateItem()方法

@Override
public Object instantiateItem(ViewGroup container, int position) {
    if (mCurTransaction == null) {
        mCurTransaction = mFragmentManager.beginTransaction();
    }

    final long itemId = getItemId(position);

    // Do we already have this fragment?
    String name = makeFragmentName(container.getId(), itemId);
    Fragment fragment = mFragmentManager.findFragmentByTag(name);
    if (fragment != null) {
        if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
        mCurTransaction.attach(fragment);
    } else {
        fragment = getItem(position);
        if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
        mCurTransaction.add(container.getId(), fragment,
                makeFragmentName(container.getId(), itemId));
    }
    if (fragment != mCurrentPrimaryItem) {
        fragment.setMenuVisibility(false);
        fragment.setUserVisibleHint(false);
    }

    return fragment;
}

在这里,并不会直接调用getItem(position)方法,而是先通过findFragmentByTag(name)去在缓存中寻找fragment,所以如果缓存存在的话,界面还是不会刷新,在这里采用一种偷懒的方式,直接清空缓存,代码如下:

package com.yueren.pyyx.adapters;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.PagerAdapter;

import com.yueren.pyyx.fragments.ImpressionDetailFragment;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by ivan on 15/7/20.
 */
public class ImpressionDetailPagerAdapter extends FragmentPagerAdapter {
    private List<Long> mIds;
    private FragmentManager mFragmentManager;
    private ArrayList<Fragment> mFragments;
    private ImpressionDetailFragment.OnCommentTargetChangeListener mListener;

    public PagerAdapter(FragmentManager fragmentManager, List<Long> ids) {
        super(fragmentManager);
        this.mFragmentManager = fragmentManager;
        this.mFragments = new ArrayList<>();
        this.mIds = ids == null ? new ArrayList<Long>() : ids;
    }

    public static PagerAdapter newInstance(FragmentManager fragmentManager, List<Long> ids) {
        return new PagerAdapter(fragmentManager, ids);
    }

    @Override
    public Fragment getItem(int position) {
        long impId = mIds.get(position);
        Fragment fragment = Fragment.newInstance(impId);
        mFragments.add(fragment);
        return fragment;
    }

    @Override
    public int getCount() {
        return mIds.size();
    }

    @Override
    public int getItemPosition(Object object) {
        return PagerAdapter.POSITION_NONE;
    }

    public long getImpressionId(int position) {
        if (position < 0 || position >= getCount()) {
            position = 0;
        }
        return mIds.isEmpty() ? -1 : mIds.get(position);
    }

    public void remove(int position) {
        clearFragmentsCache();
        mIds.remove(position);
        mFragments.clear();
        notifyDataSetChanged();
    }

    private void clearFragmentsCache() {
        FragmentTransaction transaction = mFragmentManager.beginTransaction();
        for (Fragment fragment : mFragments) {
            transaction.remove(fragment);
        }
        transaction.commit();
        transaction = null;
        mFragmentManager.executePendingTransactions();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值