前言
在项目中,我采用的是ViewPager+FragmentPagerAdapter+Fragment的方式,要实现fragment的刷新,但是发现并没有把ViewPager中的fragment替换掉,因此上网查阅了很多博客,最后解决了这个问题。
解决方法
我就直接贴上我的代码
public class MyViewPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> mFragments = new ArrayList<>();
public MyViewPagerAdapter(@NonNull FragmentManager fm, List<Fragment> mFragments) {
super(fm);
this.mFragments = mFragments;
}
@NonNull
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
}
//原本ViewPager内存中缓存了Fragment,重写该方法使adapter重新创建新的Fragment
@Override
public long getItemId(int position) {
return mFragments.get(position).hashCode();
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
主要是重写两个方法
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
设置POSITION_NONE的目的是可以执行instantiateItem,刷新Fragment就需要这行该函数。
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;}
我们发现每次创建fragment时候,FragmentManager都会通过findFragmentByTag去缓存中查找,是否存在指定tagName的Fragment,有就复用,没有就创建新的Fragment,而这里的tagName就是通过getItemId()方法生成的。
因此FragmentPagerAdapter是根据getItemId(int position)来判断当前position的Fragment是否存在的。
而getItemId的源码是:
public long getItemId(int position) {
return position;
}
这样的话getItemId返回的值并不唯一,会导致获取到的Fragment是旧的Fragment。
因此我们需要让getItemId返回一个唯一的值,因此重写该方法如下:
@Override
public long getItemId(int position) {
return mFragments.get(position).hashCode();
}
之后调用pagerAdapter的notifyDataSetChanged方法就可以实现Fragment的刷新。